113.龙芯2k1000-pmon(12)- pmon源码对env的解析

本文回答前文思考的问题 112.龙芯2k1000-pmon(11)- gzrom-dtb.bin 文件的组成-CSDN博客

env写的位置是ff000 后面的500字节,这个位置能否改动呢?

答案是:不可以!!! 否则需要改源码

找到源码:

Targets/LS2K-hj20004/ls2k/tgt_machdep.c

1. 函数tgt_mapenv

void tgt_mapenv(int (*func) __P((char *, char *)))  //参数名注意一下,后面多次用到,就是setenv

nvram = (char *)(tgt_flashmap())->fl_map_base;
	printf("nvram=%08x\n", (unsigned int)nvram);   //这句被打印了
	if (fl_devident(nvram, NULL) == 0 ||  //返回值不是0
	    cksum(nvram + NVRAM_OFFS, NVRAM_SIZE, 0) != 0) { //返回值为0,if条件不成立

这里我打印nvram出来了,nvram=0xbfc00000. 就是flash映射的虚拟地址

宏定义

NVRAM_OFFS  是个常量 0xff000

所以,env必须放在这个位置,不可修改为其他位置,否则 要么修改源码的偏移,要么就会读取出现问题。

NVRAM_SIZE  设置为492,实际应该是500,但是后面的字节都是0,所以不影响校验和。

2. cksum 函数   (Targets/LS2K-hj20004/ls2k/tgt_machdep.c)

看一下checksum的c语言计算,与前面的部分对应起来,是一致的。

参数s很明显应该与前文的命令一致,应该是500才对。

(这里我自己修改宏定义NVRAM_SIZE为500)

/*
 *  Calculate checksum. If 'set' checksum is calculated and set.
 */
static int cksum(void *p, size_t s, int set)
{
	u_int16_t sum = 0;
	u_int8_t *sp = p;
	int sz = s / 2;

	if (set) {
		*sp = 0;	/* Clear checksum */
		*(sp + 1) = 0;	/* Clear checksum */
	}
	while (sz--) {
		sum += (*sp++) << 8;
		sum += *sp++;
	}
	if (set) {
		sum = -sum;
		*(u_int8_t *) p = sum >> 8;
		*((u_int8_t *) p + 1) = sum;
	}
	return (sum);
}

校验和通过之后才会解析,设置到环境变量,否则就无效。


	nvram = (char *)(tgt_flashmap())->fl_map_base;
	printf("nvram=%08x\n", (unsigned int)nvram);   //这句被打印了
	if (fl_devident(nvram, NULL) == 0 ||  //返回值不是0
	    cksum(nvram + NVRAM_OFFS, NVRAM_SIZE, 0) != 0) { //返回值为0,if条件不成立

		printf("NVRAM is invalid!\n");
		nvram_invalid = 1;
	} else {
		nvram += NVRAM_OFFS;   //执行这个语句
		ep = nvram + 2;;    //为什么加2,就简单了,看makefile.inc
		
        while (*ep != 0) {   //循环解析出来
			char *val = 0, *p = env;
			i = 0;
			while ((*p++ = *ep++) && (ep <= nvram + NVRAM_SIZE - 1)
			       && i++ < 255) {
				if ((*(p - 1) == '=') && (val == NULL)) {
					*(p - 1) = '\0';
					val = p;
				}
			}
			if (ep <= nvram + NVRAM_SIZE - 1 && i < 255) {
				(*func) (env, val);
			//	printf("2022-03-03 : env = %s val = %s ep = %x i = %d\n", env, val,ep,i);
			} else {
				nvram_invalid = 2;
			//	printf("2022-03-03 : nvram_invalid ep = %x i = %d\n", ep,i);
				break;
			}
		}

	}

3. 环境变量的解析

FR=1\x00al=(usb0,0)/boot/vmlinuz\x00append='console=ttyS0,115200 noinitrd root=/dev/sda2  rootfstype=ext4 rootwait rw'\x00al1=(wd0,0)/vmlinuz\x00

环境变量的解析就是找到字符‘\0’,然后分开就行

中间找到等号,把等号赋值为字符‘\0’,这样就分开了环境变量和对应的值

(*func) (env, val);

其中env就是环境变量的名字,val就是值。两个都是字符串。

4.  看一下_setenv 函数

主要作用就是把环境变量的名字和值设置到全局数组envvar中,

如果原来存在改环境变量,则修改原来对应的值,

如果不存在则新增一个环境变量。

这个数组最多能够保存64个成员,但是64并不是可以自定义的环境变量的个数!!!

static int
_setenv (name, value)
    char *name, *value;
{
    struct envpair *ep;
    struct envpair *bp = 0;
    const struct stdenv *sp;

    if ((sp = getstdenv (name)) != 0) { //使用名字查询,是否在标准环境变量表中,不存在返回0
		if (sp-> chgfunc && !(*sp->chgfunc) (name, value)) //如果在标准表中,看这个是否又对应的修改函数,有则调用该修改函数
		    return 0;
		//如果标准环境变量表中存在值,且没有对应的修改函数,则看原来的值与value是不是相等,相等返回1,否则0,envinited为表示第一次初始化,否则为修改
		if (sp->values && _matchval (sp, value) < 0 && envinited) {
		    printf ("%s: bad %s value, try [%s]\n", value, name, sp->values);  //不相等则提示使用原来的默认值,而提示新的值是bad
		    return 0;
		}
    }

    for (ep = envvar; ep < &envvar[NVAR]; ep++) {  //在环境变量数组中找,最多64个环境变量
		if (!ep->name && !bp)  //数组中,环境变量名为空的,并且bp指针也是空的,就是找到一个空位了
		  bp = ep;
		else if (ep->name && striequ (name, ep->name))  //有相同的就退出循环
		  break;
    }
    
    if (ep < &envvar[NVAR]) {   //有相同的,是break出的循环
		/* must have got a match, free old value */
		if (ep->value) {
		    free (ep->value); ep->value = 0;  //释放原来的空间
		}
    } else if (bp) { //没有相同的,存在有envvar数组中第一个空白的位置
		/* new entry */
		ep = bp;
		if (!(ep->name = malloc (strlen (name) + 1)))  //分配空间
		  return 0;
		strcpy (ep->name, name);  //数据拷贝到空间中
    } else {  //envvar数组中没有找到空白的位置,已经填满了
		return 0;
    }

    if (value) { //value存在
		if (!(ep->value = malloc (strlen (value) + 1))) {  //分配空间
		    free (ep->name); ep->name = 0;
		    return 0;
		}
		strcpy (ep->value, value);  
    }

    return 1;
}

4.1  有一个标准环境变量表 (env.c 中)

这个表也会解析到全局环境变量数组中。

static struct stdenv {
    char           *name;   //环境变量的名称
    char           *init;   //初始化的值
    char           *values;  //所有可用的值
    int		   (*chgfunc) __P((char *, char *));  //修改该环境变量的对应函数指针,
} stdenvtab[] = {
    {"brkcmd", "l -r @cpc 1", 0},
#ifdef HAVE_QUAD
    {"datasize", "-b", "-b -h -w -d"},
#else
    {"datasize", "-b", "-b -h -w"},
#endif
    {"dlecho", "off", "off on lfeed"},
    {"dlproto", "none", "none XonXoff EtxAck"},
#ifdef INET
    {"bootp",	"no", "no sec pri save"},
#endif
    {"hostport", "tty0", 0},
    {"inalpha", "hex", "hex symbol"},
    {"inbase", INBASE_DEFAULT, INBASE_STRING},
#if NCMD_MORE > 0
    {"moresz", "10", 0, chg_moresz},
#endif
    {"prompt", "PMON> ", 0},
    {"regstyle", "sw", "hw sw"},
#ifdef HAVE_QUAD
    {"regsize", "32", "32 64"},
#endif
    {"rptcmd", "trace", "off on trace"},
    {"trabort", "^K", 0},
    {"ulcr", "cr", "cr lf crlf"},
    {"uleof", "%", 0},
#ifdef PMON_DEBUGGER /* XXX: Patrik temp */
    {"validpc", "_ftext etext", 0, chg_validpc},
#endif
    {"heaptop", SETCLIENTPC, 0, chg_heaptop},
    {"showsym", "yes", "no yes"},
    {"fpfmt", "both", "both double single none"},
    {"fpdis", "yes", "no yes"},
#if defined(TGT_DEFENV)
    TGT_DEFENV,
#endif
    {0}
};

这个数组中最多放64个环境变量。(但是注意,能够自己定义的应该小于30,原因往下看

他们的存储方式都是存放字符串指针。

环境变量就是以数组的形式存放在这个envvar数组中。

5.还有一些默认环境变量设置(代码中标识了8个)

也就是最多能自定义的是64-8= 56个? 不,还要减掉标准的环境变量表中的。

void tgt_mapenv(int (*func) __P((char *, char *)))  //参数名注意一下,后面多次用到,就是setenv
{
	char *ep;
	char env[512];
	char *nvram;
	int i;

	/*
	 *  Check integrity of the NVRAM env area. If not in order
	 *  initialize it to empty.
	 */
	printf("in envinit\n");
#ifdef NVRAM_IN_FLASH    //从打印的结果看,这个宏定义被定义了
	nvram = (char *)(tgt_flashmap())->fl_map_base;
	printf("nvram=%08x\n", (unsigned int)nvram);   //这句被打印了
	if (fl_devident(nvram, NULL) == 0 ||  //返回值不是0
	    cksum(nvram + NVRAM_OFFS, NVRAM_SIZE, 0) != 0) { //返回值为0,if条件不成立
#else
	nvram = (char *)malloc(512);
	nvram_get(nvram);
	if (cksum(nvram, NVRAM_SIZE, 0) != 0) {
#endif
		printf("NVRAM is invalid!\n");
		nvram_invalid = 1;
	} else {
#ifdef NVRAM_IN_FLASH
		nvram += NVRAM_OFFS;   //执行这个语句
		ep = nvram + 2;;    //为什么加2,就简单了,看makefile.inc

		while (*ep != 0) {
			char *val = 0, *p = env;
			i = 0;
			while ((*p++ = *ep++) && (ep <= nvram + NVRAM_SIZE - 1)
			       && i++ < 255) {
				if ((*(p - 1) == '=') && (val == NULL)) {
					*(p - 1) = '\0';
					val = p;
				}
			}
			if (ep <= nvram + NVRAM_SIZE - 1 && i < 255) {
				(*func) (env, val);
			//	printf("2022-03-03 : env = %s val = %s ep = %x i = %d\n", env, val,ep,i);
			} else {
				nvram_invalid = 2;
			//	printf("2022-03-03 : nvram_invalid ep = %x i = %d\n", ep,i);
				break;
			}
		}
#endif
	}

	printf("NVRAM@%x\n", (u_int32_t) nvram);
#ifdef NVRAM_IN_FLASH
	printf("ACTIVECOM_OFFS = %d, = 0x%x\n", ACTIVECOM_OFFS, ACTIVECOM_OFFS);
	printf("MASTER_BRIDGE_OFFS = %d, = 0x%x\n", MASTER_BRIDGE_OFFS,
	       MASTER_BRIDGE_OFFS);
	printf("before :activecom = %d. em_enable = %d\n", activecom,
	       em_enable);
//      printf("nuram[MASTER_BRIDGE_OFFS] = %d.\n" nvram[MASTER_BRIDGE_OFFS]);
	if (!nvram_invalid)
		bcopy(&nvram[ACTIVECOM_OFFS], &activecom, 1);
	else
		activecom = 3 /*1 */ ;
	sprintf(env, "0x%02x", activecom);      
	(*func) ("activecom", env);	/*tangyt */    //1.设置环境变量activecom

	if (!nvram_invalid)
		bcopy(&nvram[MASTER_BRIDGE_OFFS], &em_enable, 1);
	else
		em_enable = 3 /*1 */ ;
	sprintf(env, "0x%02x", em_enable);
	(*func) ("em_enable", env);	/*tangyt */      //2.设置环境变量em_enable

	printf("activecom = %d.   em_enable = %d.\n", activecom, em_enable);
#endif
	/*
	 *  Ethernet address for Galileo ethernet is stored in the last
	 *  six bytes of nvram storage. Set environment to it.
	 */

	bcopy(&nvram[ETHER_OFFS], hwethadr, 6);  //ETHER_OFFS = 494,最后6个字节可以设置mac地址,实际是0
	sprintf(env, "%02x:%02x:%02x:%02x:%02x:%02x", hwethadr[0], hwethadr[1],
		hwethadr[2], hwethadr[3], hwethadr[4], hwethadr[5]);
	(*func) ("ethaddr", env);    //3. 设置环境变量ethaddr

#ifndef NVRAM_IN_FLASH
	free(nvram);
#endif

#ifdef no_thank_you
	(*func) ("vxWorks", env);
#endif

	sprintf(env, "%d", memorysize / (1024 * 1024));
	(*func) ("memsize", env);     //4. 设置环境变量memsize

	sprintf(env, "%d", memorysize_high / (1024 * 1024));
	(*func) ("highmemsize", env);   //5.0设置环境变量highmemsize

	sprintf(env, "%d", md_pipefreq);
	(*func) ("cpuclock", env);      //6.设置环境变量 cpuclock

	sprintf(env, "%d", md_cpufreq);
	(*func) ("busclock", env);      //7.设置环境变量 busclock

	(*func) ("systype", SYSTYPE);   //8.设置环境变量 systype  

}

6.  看一下实际的环境变量

能自定义的环境变量,应该是低于34个。

否则会导致一些默认的环境变量无法解析出来。

分析结束。请各位指教。

自己生成一个env呢?写到flash的oxff000的偏移地址如何?

如果只是增加环境变量,是不是就可以不用编译pmon了?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/419668.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

flink下载安装部署说明

下载 下载地址 flink-1.16.2下载安装包&#xff0c;flink-1.16.2-bin-scala-2.12.zip资源-CSDN文库 安装 解压目录 启动集群 ./start-cluster.sh 提交作业 ./bin/flink run examples/streaming/WordCount.jar 查看日志 停止集群 ./bin/stop-cluster.sh 开启webui vim c…

adb下载安装及使用教程

adb下载安装及使用教程 一、ADB的介绍1.ADB是什么&#xff1f;2.内容简介3.ADB常用命令1. ADB查看设备2. ADB安装软件3. ADB卸载软件4. ADB登录设备shell5. ADB从电脑上发送文件到设备6. ADB从设备上下载文件到电脑7. ADB显示帮助信息 4.为什么要用ADB 二、ADB的下载1.Windows版…

Components 概览

Components 概览 Compose 中的组件被声明为 Composable &#xff0c;中文意思是可组成的/可合成&#xff0c;也为了与原来 xml 和 View&#xff08;ViewGroup&#xff09;做出区分。在使用过程中会体会到&#xff0c;使用 Compose 声明 UI 更像是在拼图。 Compose 提供了 Mat…

2024年sCrypt编程马拉松即将开幕

BSV区块链的建设者们&#xff0c;你们在哪&#xff1f;2024年sCrypt编程马拉松即将拉开帷幕&#xff01; 2024年3月16日至17日&#xff0c;我们将在旧金山市举办一场以比特币智能合约&#xff08;即 sCrypt&#xff09;和比特币通证&#xff08;如Ordinals&#xff09;相结合为…

jstat命令查看jvm的GC信息

文章目录 前言jstat命令查看jvm的GC信息1. 概述2. 应用堆内存水位阀值大小怎么确定3. 使用 jps 命令查看 Java 进程的进程号&#xff08;PID&#xff09;![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/5097401443314e9d808a83b694dbc6e5.png)4. jstat用法5. 类加载…

农产品质量追溯系统—简介

概要 农产品质量安全事关广大人民群众的食用安全和身体健康。解决农产品质量安全问题,需要从源头开始抓好、抓实农产品安全监管工作。通过建立从产地到市场的全程质量控制系统和追溯制度,对农产品产地环境、生产过程、产品检测、包装盒标识等关键环节进行监督管理,提高广大…

php 把数字转化为大写中文

1. 120002129.25 转化后壹億贰仟萬贰仟壹佰贰拾玖圆贰角伍分2. 12000.2145 转化后壹萬贰仟圆贰角壹分肆厘伍毫3. 1020001211 转化后壹拾億贰仟萬壹仟贰佰壹拾壹圆整大致思路这样的: 从小数点分割成两部分,整数部分和小数部分分别处理。 整数四个一组进行处理,用substr函数分…

SpringBoot 事务失效及其对应解决办法

简介 本文主要讲述Spring事务会去什么情况下失效及其解决办法 Spring 通过AOP 进行事务控制&#xff0c;如果操作数据库报异常&#xff0c;则会进行回滚&#xff1b;如果没有报异常则会提交事务&#xff1b;但是&#xff0c;如果Spring 事务失效&#xff0c;会导致数据缺失/重…

几个原创文章自动生成软件推荐

在数字化时代&#xff0c;原创文章的重要性越来越被重视&#xff0c;但是频繁的写作工作却也耗费大量时间和精力。原创文章自动生成软件能够帮助大家快速生成各种类型的原创文章&#xff0c;节省时间和精力。本文将介绍6款不同的原创文章自动生成软件&#xff0c;并介绍一款知名…

mysql 常用命令练习

管理表格从表中查询数据从多个表查询修改数据sql变量类型 管理表格 创建一个包含三列的新表 CREATE TABLE products (id INT,name VARCHAR(255) NOT NULL,price INT DEFAULT 0,PRIMARY KEY(id) // 自增 ); 从数据库中删除表 DROP TABLE product; 向表中添加新列 ALTER TAB…

WPF中如何设置自定义控件

1.圆角按钮的设置&#xff1a; 众所周知在WPF中自带有提示信息&#xff0c;当我问创建Button时&#xff0c;点击空格出现如下可选设置 带有小扳手&#x1f527;图标为相应的属性&#xff0c;如果Button有CornerRadius&#xff08;角半径&#xff09;属性就能够直接设置Button实…

记录 android studio 通过安装NDK 编译C文件,得到需要的so文件

只怪自己太健忘&#xff0c;每次网上查了一圈&#xff0c;搞定后&#xff0c;再遇到又发现不会操作了&#xff0c;特此记下 不废话直接上步骤 &#xff08;1&#xff09; 进入AS的settinging如下界面 &#xff08;2&#xff09;选中图片箭头两个文件 进行下载 &#xff08;…

Jmeter分布式部署

前期准备&#xff1a; 1. 控制机一台&#xff0c;代理机一台&#xff0c;Jmeter安装包 操作步骤&#xff1a; 1. Linux安装Jmeter&#xff08;windows安装教程自己搜一下&#xff09; 1.1创建一个单独的文件夹(jmeter)&#xff0c;用来存放Jmeter的安装包 mkdir jmeter 1.2…

docker安装使用基础

一、镜像安装 我的docker安装在centos7虚拟机上&#xff08;关于虚拟机网络设置此前已有总结VMware 搭建centos虚拟机网络设置_vmware centos 网络配置-CSDN博客&#xff09;&#xff0c;现在默认操作系统和网络已就位。 1、安装工具包 # 安装操作一般都需要管理员权限&…

【leetcode】 剑指 Offer学习计划(java版本含注释)(下)

目录 前言第十六天&#xff08;排序&#xff09;剑指 Offer 45. 把数组排成最小的数&#xff08;中等&#xff09;剑指 Offer 61. 扑克牌中的顺子&#xff08;简单&#xff09; 第十七天&#xff08;排序&#xff09;剑指 Offer 40. 最小的k个数&#xff08;简单&#xff09; 第…

STL常见容器(set/multiset)---C++

STL常见容器目录&#xff1a; 7. set/multiset 容器7.1 set/multiset 基本概念7.2 set构造和赋值7.3 set大小和交换7.4 set插入和删除7.5 set查找和统计7.6 set和multiset区别7.6.1 pair对组创建7.6.2 set和multiset区别 7.7 set容器排序7.7.1 内置数据类型7.7.2 自定义数据类型…

记录 关于navicat连接数据库报错1045的问题

重装数据库之后就连接不上了 报错1045 而网上的解决方案大都是更改数据库密码&#xff0c;但是我在第一步就被卡住无法更改密码&#xff0c;输入指令也报错&#xff0c;检查的环境变量也没错&#xff0c;经过长时间的试错终于找到解决了办法 解决办法 删除data文件夹 如果无法…

吸引用户购买产品的文案技巧,媒介盒子揭秘

在营销过程中&#xff0c;想要吸引用户购买产品&#xff0c;文案是重中之重&#xff0c;需要一定的技巧才能将文案写好&#xff0c;今天媒介盒子就来和大家聊聊&#xff1a;在品牌推广中如何通过一些小技巧吸引用户购买产品&#xff1a; 一、 少说专业术语 少说行话、黑话。多…

如何选择合适的幻兽帕鲁服务器CPU核心数和内存大小,避免丢包和延迟高?

根据幻兽帕鲁服务器的实际案例分析选择合适的CPU核心数和内存大小以避免丢包和延迟高&#xff0c;首先需要考虑的是服务器的性能需求。幻兽帕鲁服务器推荐使用4核CPU和16GB内存&#xff0c;建议使用32GB以上的内存才能稳定运行。这表明对于幻兽帕鲁这样的游戏服务器来说&#x…

2024有哪些免费的mac苹果电脑深度清理工具?CleanMyMac X

苹果电脑用户们&#xff0c;你们是否经常感到你们的Mac变得不再像刚拆封时那样迅速、流畅&#xff1f;可能是时候对你的苹果电脑进行一次深度清理了。在这个时刻&#xff0c;拥有一些高效的深度清理工具就显得尤为重要。今天&#xff0c;我将介绍几款优秀的苹果电脑深度清理工具…