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

📄 ldatags.c

📁 umon bootloader source code, support mips cpu.
💻 C
字号:
/* ldatags:
 *  Load (install) ARM Tags for booting Linux.
 *
 *	General notice:
 *	This code is part of a boot-monitor package developed as a generic base
 *	platform for embedded system designs.  As such, it is likely to be
 *	distributed to various projects beyond the control of the original
 *	author.  Please notify the author of any enhancements made or bugs found
 *	so that all may benefit from the changes.  In addition, notification back
 *	to the author will allow the new user to pick up changes that may have
 *	been made by other users after this version of the code was distributed.
 *
 *	Note1: the majority of this code was edited with 4-space tabs.
 *	Note2: as more and more contributions are accepted, the term "author"
 *		   is becoming a mis-representation of credit.
 *
 *	Original author:	Ed Sutter
 *	Email:				esutter@lucent.com
 *	Phone:				908-582-2351
 */
#include "config.h"
#include "stddefs.h"
#include "genlib.h"
#include "ether.h"
#include "cli.h"
#include "tfs.h"
#include "tfsprivate.h"

#define __PACKED__	__attribute__ ((packed))
#define TAG_SIZE(a)		((sizeof(a) + sizeof(struct tag_hdr))/4)
#define STR_LEN(string)	(sizeof(string) - 1)

#define MEM32_SIZE		"mem32_size="
#define MEM32_START		"mem32_start="
#define CORE_FLAGS		"core_flags="
#define CORE_PGSIZE		"core_pgsize="
#define CORE_ROOTDEV	"core_rootdev="
#define INITRD_SIZE		"initrd_size="
#define INITRD_START	"initrd_start="
#define RAMDISK_FLAGS	"ramdisk_flags="
#define RAMDISK_SIZE	"ramdisk_size="
#define RAMDISK_START	"ramdisk_start="
#define SERIAL_HI		"serial_hi="
#define SERIAL_LO		"serial_lo="
#define CMDLINE			"cmdline="
#define CMDLINE_APP		"cmdline_append="
#define REVISION		"revision="

void sno_mac_warning(int);
void initrd_file_warning(int);

#ifdef ATAG_SPACE_DEFINED
extern int atag_space, end_atag_space;
#endif

#define CLISIZE			1024

/* Tag specification defaults:
 */
#define RAMDISK_MAJOR	1
#define PAGE_SIZE		4096
#define PHYS_OFFSET		0x20000000
#define MEM_SIZE		0x01e00000

/* Tag identifiers:
 */
#define ATAG_NONE		0x00000000
#define ATAG_CORE		0x54410001
#define ATAG_MEM		0x54410002
#define ATAG_VIDEOTEXT	0x54410003
#define ATAG_RAMDISK	0x54410004
#define ATAG_INITRD		0x54410005
#define ATAG_INITRD2	0x54420005
#define ATAG_SERIAL		0x54410006
#define ATAG_REVISION	0x54410007
#define ATAG_VIDEOLFB	0x54410008
#define ATAG_CMDLINE	0x54410009
#define ATAG_ACORN		0x41000101
#define ATAG_MEMCLK		0x41000402
#define ATAG_SNOMAC		ATAG_SERIAL

/* Tag structures:
 */
struct tag_hdr {
	ulong size;
	ulong tag;
}__PACKED__;

struct tag_core {
	ulong flags;
	ulong pgsize;
	ulong rootdev;
}__PACKED__;

struct tag_mem32 {
	ulong size;
	ulong start;
}__PACKED__;

union tag_snomac {
	struct tag_serial {
		ulong hi;
		ulong lo;
	} serial;
	struct tag_mac {
		char mac[8];	/* only use first 6 bytes */
	} mac;
}__PACKED__;

struct tag_initrd {
	ulong start;
	ulong size;
}__PACKED__;

struct tag_ramdisk {
	ulong flags;
	ulong size;
	ulong start;
}__PACKED__;

struct tag_cmdline {
	char cmdline[CLISIZE];
}__PACKED__;

struct tag_revno {
	ulong rev;
}__PACKED__;

struct init_tags {
	struct tag_hdr		hdr1;
	struct tag_core		core;
	struct tag_hdr		hdr2;
	struct tag_mem32	mem;
	struct tag_hdr		hdr3;
	union tag_snomac	snomac;
	struct tag_hdr		hdr4;
	struct tag_ramdisk	ramdisk;
	struct tag_hdr		hdr5;
	struct tag_initrd	initrd;
	struct tag_hdr		hdr6;
	struct tag_cmdline	cmdline;
	struct tag_hdr		hdr7;
	struct tag_revno	revno;
	struct tag_hdr		hdr_last;
}__PACKED__;

/* This is the default tag list.  All entries in this list can
 * be overridden by sub-commands within the ldatags command.
 */
static struct init_tags inittag = {
	{ TAG_SIZE(struct tag_core), ATAG_CORE },
	{ 1, PAGE_SIZE, 0xff },

	{ TAG_SIZE(struct tag_mem32), ATAG_MEM },
	{ MEM_SIZE, PHYS_OFFSET },

	{ TAG_SIZE(union tag_snomac), ATAG_SNOMAC },
	{ {0xffffffff, 0xffffffff} },

	{ TAG_SIZE(struct tag_ramdisk), ATAG_RAMDISK },
	{ 0, 0, 0 },

	{ TAG_SIZE(struct tag_initrd), ATAG_INITRD2 },
	{ 0, 0 },

	{ TAG_SIZE(struct tag_cmdline), ATAG_CMDLINE },
	{ {0} },

	{ TAG_SIZE(struct tag_revno), ATAG_REVISION },
	{ 0 },

	{ 0, ATAG_NONE },
};


char *ldatagsHelp[] = {
	"Install ARM tags for Linux startup.",
	"[-a:cf:imv] [sub-cmd1 sub-cmd2 ...]",
	"Options:",
	" -a {addr}    tag list address",
	" -c           clear tag list memory",
	" -f {fname}   initrd filename",
	" -i           init default tag list",
	" -m           load MAC address into serial_no tag",
	" -v           enable verbosity",
	"Sub-commands:",
	"   " CORE_FLAGS "{value}",
	"   " CORE_PGSIZE "{value}",
	"   " CORE_ROOTDEV "{value}",
	"   " MEM32_SIZE "{value}",
	"   " MEM32_START "{value}",
	"   " SERIAL_LO "{value}       (serial hi/lo overrides -m)",
	"   " SERIAL_HI "{value}",
	"   " INITRD_SIZE "{value}     (initrd size/start overrides -f)",
	"   " INITRD_START "{value}",
	"   " RAMDISK_FLAGS "{value}",
	"   " RAMDISK_SIZE "{value}",
	"   " RAMDISK_START "{value}",
	"   " REVISION "{value}",
	"   " CMDLINE "{string}",
	"   " CMDLINE_APP "{string}",
	0
};


int
ldatags(int argc,char *argv[])
{
	TFILE	*tfp;
	char	*eadd, *initrd_fname;
	struct init_tags *tagaddr;
	int		opt, verbose, arg, clear, init, mac, len;
	int		sno_mac_warned, initrd_file_warned;

	initrd_fname = 0;
	sno_mac_warned = initrd_file_warned = 0;
	mac = init = verbose = clear = 0;
#ifdef ATAG_SPACE_DEFINED
	tagaddr = (struct init_tags *)&atag_space;
#else
	tagaddr = (struct init_tags *)getAppRamStart();
#endif
	while((opt=getopt(argc,argv,"a:cf:imv")) != -1) {
		switch(opt) {
		case 'a':	/* Override default tag list address. */
			tagaddr = (struct init_tags *)strtoul(optarg,0,0);
			break;
		case 'c':	/* Clear the tag list space. */
			clear++;
			break;
		case 'f':	/* Initrd filename. */
			initrd_fname = optarg;
			break;
		case 'i':	/* Initialize tag list with defaults. */
			init++;
			break;
		case 'm':	/* Load MAC address into list. */
			mac++;
			break;
		case 'v':	/* Enable verbosity. */
			verbose++;
			break;
		default:
			return(CMD_PARAM_ERROR);
		}
	}

#ifdef ATAG_SPACE_DEFINED
	/* If the ATAG space is allocated externally (usually in rom.lnk file),
	 * then if at this point the tag address still points to that space, 
	 * we must start by verifying that the allocated space is large enough
	 * to hold the init_tags structure...
	 */
	if (tagaddr == (struct init_tags *)&atag_space) {
		if (((int)&end_atag_space - (int)&atag_space) < sizeof(struct init_tags)) {
			printf("Error: the size of struct init_tags (%d) is larger than\n",
				sizeof(struct init_tags));
			printf("       the size of the allocated atag space (%d bytes).\n",
				((int)&end_atag_space - (int)&atag_space));
			return(CMD_FAILURE);
		}
	}
#endif

	if (clear) {
		memset((char *)tagaddr,0,sizeof(struct init_tags));
		if (verbose)
			printf("Tagspace at 0x%lx cleared\n",(long)tagaddr);
		return(CMD_SUCCESS);
	}

	/* If -i specified, then load default tag list for starters...
	 */
	if (init) 
		memcpy((char *)tagaddr,(char *)&inittag,sizeof(struct init_tags));
		
	/* Insert this board's MAC address:
	 */
	if (mac) {
		memset(tagaddr->snomac.mac.mac,0,8);
		eadd = getenv("ETHERADD");
		if (eadd) {
			if (EtherToBin(eadd,tagaddr->snomac.mac.mac) < 0)
				return(CMD_FAILURE);
		}
		else {
			printf("ETHERADD shell var not set.\n");
			return(CMD_FAILURE);
		}
	}

	if (initrd_fname) {
		tfp = tfsstat(initrd_fname);
		if (!tfp) {
			printf("No such file: %s\n",initrd_fname);
			return(CMD_FAILURE);
		}
		tagaddr->initrd.size = (ulong)TFS_SIZE(tfp);
		tagaddr->initrd.start = (ulong)TFS_BASE(tfp);
	}

	/* Process the command line arguments:
	 */
	for(arg=optind;arg<argc;arg++) {
		if (strncmp(argv[arg],CORE_FLAGS,STR_LEN(CORE_FLAGS)) == 0) {
			tagaddr->core.flags =
				strtoul(argv[arg]+STR_LEN(CORE_FLAGS),0,0);
		}
		else if (strncmp(argv[arg],CORE_PGSIZE,STR_LEN(CORE_PGSIZE)) == 0) {
			tagaddr->core.pgsize =
				strtoul(argv[arg]+STR_LEN(CORE_PGSIZE),0,0);
		}
		else if (strncmp(argv[arg],CORE_ROOTDEV,STR_LEN(CORE_ROOTDEV)) == 0) {
			tagaddr->core.rootdev =
				strtoul(argv[arg]+STR_LEN(CORE_ROOTDEV),0,0);
		}
		else if (strncmp(argv[arg],MEM32_SIZE,STR_LEN(MEM32_SIZE)) == 0) {
			tagaddr->mem.size =
				strtoul(argv[arg]+STR_LEN(MEM32_SIZE),0,0);
		}
		else if (strncmp(argv[arg],MEM32_START,STR_LEN(MEM32_START)) == 0) {
			tagaddr->mem.start =
				strtoul(argv[arg]+STR_LEN(MEM32_START),0,0);
		}
		else if (strncmp(argv[arg],INITRD_SIZE,STR_LEN(INITRD_SIZE)) == 0) {
			if (initrd_fname)
				initrd_file_warning(initrd_file_warned++);
			tagaddr->initrd.size =
				strtoul(argv[arg]+STR_LEN(INITRD_SIZE),0,0);
		}
		else if (strncmp(argv[arg],INITRD_START,STR_LEN(INITRD_START)) == 0) {
			if (initrd_fname)
				initrd_file_warning(initrd_file_warned++);
			tagaddr->initrd.start =
				strtoul(argv[arg]+STR_LEN(INITRD_START),0,0);
		}
		else if (strncmp(argv[arg],RAMDISK_FLAGS,STR_LEN(RAMDISK_FLAGS)) == 0) {
			tagaddr->ramdisk.flags =
				strtoul(argv[arg]+STR_LEN(RAMDISK_FLAGS),0,0);
		}
		else if (strncmp(argv[arg],RAMDISK_SIZE,STR_LEN(RAMDISK_SIZE)) == 0) {
			tagaddr->ramdisk.size =
				strtoul(argv[arg]+STR_LEN(RAMDISK_SIZE),0,0);
		}
		else if (strncmp(argv[arg],RAMDISK_START,STR_LEN(RAMDISK_START)) == 0) {
			tagaddr->ramdisk.start =
				strtoul(argv[arg]+STR_LEN(RAMDISK_START),0,0);
		}
		else if (strncmp(argv[arg],SERIAL_HI,STR_LEN(SERIAL_HI)) == 0) {
			if (mac) 
				sno_mac_warning(sno_mac_warned++);
			mac = 0;
			tagaddr->snomac.serial.hi =
				strtoul(argv[arg]+STR_LEN(SERIAL_HI),0,0);
		}
		else if (strncmp(argv[arg],SERIAL_LO,STR_LEN(SERIAL_LO)) == 0) {
			if (mac) 
				sno_mac_warning(sno_mac_warned++);
			mac = 0;
			tagaddr->snomac.serial.lo =
				strtoul(argv[arg]+STR_LEN(SERIAL_LO),0,0);
		}
		else if (strncmp(argv[arg],CMDLINE,STR_LEN(CMDLINE)) == 0) {
			len = strlen(argv[arg]+STR_LEN(CMDLINE));
			if (len > CLISIZE-1)
				printf("Kernel cli too big (%d>%d)\n",len,CLISIZE);
			else
				strcpy(tagaddr->cmdline.cmdline,argv[arg]+STR_LEN(CMDLINE));
		}
		else if (strncmp(argv[arg],CMDLINE_APP,STR_LEN(CMDLINE_APP)) == 0) {
			len = strlen(argv[arg]+STR_LEN(CMDLINE_APP));
			len += strlen(tagaddr->cmdline.cmdline);
			if (len > CLISIZE-1)
				printf("Kernel cli too big (%d>%d)\n",len,CLISIZE);
			else
				strcat(tagaddr->cmdline.cmdline,argv[arg]+STR_LEN(CMDLINE_APP));
		}
		else if (strncmp(argv[arg],REVISION,STR_LEN(REVISION)) == 0) {
			tagaddr->revno.rev =
				strtoul(argv[arg]+STR_LEN(REVISION),0,0);
		}
		else {
			printf("Unrecognized sub-command: %s\n",argv[arg]);
			return(CMD_FAILURE);
		}
	}

	if (verbose) {
		printf("ATAGS (%d bytes) at 0x%lx...\n",
			sizeof(struct init_tags),(long)tagaddr);
		printf(" Core (flags/pgsize/rootdev) = 0x%lx/0x%0lx/0x%lx\n",
			tagaddr->core.flags,tagaddr->core.pgsize,tagaddr->core.rootdev);
		printf(" Mem32 (size/offset) = 0x%08lx/0x%08lx\n",
			tagaddr->mem.size,tagaddr->mem.start);
		if (mac) {
			printf(" Mac = %02x:%02x:%02x:%02x:%02x:%02x\n",
				tagaddr->snomac.mac.mac[0], tagaddr->snomac.mac.mac[1],
				tagaddr->snomac.mac.mac[2], tagaddr->snomac.mac.mac[3],
				tagaddr->snomac.mac.mac[4], tagaddr->snomac.mac.mac[5]);
		}
		else {
			printf(" Serial (hi/lo) = 0x%08lx/0x%08lx\n",
				tagaddr->snomac.serial.hi, tagaddr->snomac.serial.lo);
		}
		printf(" Ramdisk (flags/size/start) = 0x%lx/0x%lx/0x%lx\n",
			tagaddr->ramdisk.flags, tagaddr->ramdisk.size,
			tagaddr->ramdisk.start);

		printf(" Initrd (size/start) = 0x%lx/0x%lx\n",
			tagaddr->initrd.size, tagaddr->initrd.start);

		printf(" Cmdline = <%s>\n",tagaddr->cmdline.cmdline);
	}

	return(CMD_SUCCESS);
}

void
sno_mac_warning(int already_warned)
{
	if (already_warned)
		return;

	printf("Warning: serialno command overrides -m option.\n");
}

void
initrd_file_warning(int already_warned)
{
	if (already_warned)
		return;

	printf("Warning: initrd command overrides -f option.\n");
}

⌨️ 快捷键说明

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