移植u-boot-2016.11到JZ2440(六:修改源码之环境变量、裁剪uboot与设置分区)

目录

6. 修改源码之裁剪uboot、设置分区与环境变量
    6.1 裁剪uboot

        6.1.1 裁剪include/configs/jz2440.h文件
            6.1.1.1 去掉USB支持
            6.1.1.2 去掉RTC
            6.1.1.3 去掉BOOTP选项
            6.1.1.4 去掉部分不需要的命令行配置
            6.1.1.5 去掉文件系统
        6.1.2 裁剪configs/jz2440_defconfig文件
        6.1.3 重新编译
    6.2 设置分区
        6.2.1 修改源码设置分区
        6.2.2 使用分区名烧写文件
    6.3 环境变量
        6.3.1 修改默认环境变量
        6.3.2 修改支持保存环境变量


6. 修改源码之裁剪uboot、设置分区与环境变量

6.1 裁剪uboot

    在上一节移植u-boot-2016.11到JZ2440(五:修改源码之支持DM9000C网卡)修改完的u-boot.bin达到了480多KB,其中有很多无用的代码,下面我们首先来裁剪uboot。在配置文件include/configs/jz2440.h文件里面定义的很多宏,部分宏决定了会编译哪些代码进uboot,我们也许用不上的就要去掉。

6.1.1 裁剪include/configs/jz2440.h文件

6.1.1.1 去掉USB支持

/************************************************************
 * USB support (currently only works with D-cache off)
 ************************************************************/
#if 0
#define CONFIG_USB_OHCI
#define CONFIG_USB_OHCI_S3C24XX
#define CONFIG_DOS_PARTITION
#endif

6.1.1.2 去掉RTC

/************************************************************
 * RTC
 ************************************************************/
#if 0
#define CONFIG_RTC_S3C24X0
#endif

6.1.1.3 去掉BOOTP选项

/*
 * BOOTP options
 */
#if 0
#define CONFIG_BOOTP_BOOTFILESIZE
#define CONFIG_BOOTP_BOOTPATH
#define CONFIG_BOOTP_GATEWAY
#define CONFIG_BOOTP_HOSTNAME
#endif

6.1.1.4 去掉部分不需要的命令行配置

/*
 * Command line configuration.
 */
#if 0
#define CONFIG_CMD_BSP
#define CONFIG_CMD_DATE
#endif

6.1.1.5 去掉文件系统

/*
 * File system
 */
#if 0
#define CONFIG_CMD_UBIFS
#define CONFIG_MTD_DEVICE
#define CONFIG_MTD_PARTITIONS
#define CONFIG_YAFFS2
#define CONFIG_RBTREE
#endif
#define CONFIG_CMD_MTDPARTS

6.1.2 裁剪configs/jz2440_defconfig文件

    修改configs/jz2440_defconfig文件,如下:

CONFIG_ARM=y
CONFIG_TARGET_JZ2440=y
CONFIG_BOOTDELAY=5
# CONFIG_SYS_STDIO_DEREGISTER is not set
# CONFIG_DISPLAY_BOARDINFO is not set
# CONFIG_HUSH_PARSER=y
CONFIG_SYS_PROMPT="JZ2440 # "
# CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
# CONFIG_CMD_DHCP=y
CONFIG_CMD_PING=y
# CONFIG_CMD_CACHE=y
# CONFIG_CMD_EXT2=y
# CONFIG_CMD_FAT=y
# CONFIG_CMD_UBI=y
# CONFIG_USB=y
# CONFIG_USB_STORAGE=y
# CONFIG_USB_KEYBOARD=y

6.1.3 重新编译

    执行./remake.sh重新编译,新的u-boot.bin只有233KB左右了,如下:
    移植u-boot-2016.11到JZ2440(六:修改源码之环境变量、裁剪uboot与设置分区)

6.2 设置分区

6.2.1 修改源码设置分区

    我们可以使用mtdparts命令,得到如下输出:
    移植u-boot-2016.11到JZ2440(六:修改源码之环境变量、裁剪uboot与设置分区)
    查找“mtdids not defined, no default present”字符串定位到mtdparts_init()函数中如下代码(cmd/mtdparts.c文件)

int mtdparts_init(void)
{
    	/* get variables */
	ids = getenv("mtdids");    
	parts = getenv("mtdparts");
	current_partition = getenv("partition");

        ... ...

        /* if mtdids varible is empty try to use defaults */
	if (!ids) {
		if (mtdids_default) {
			debug("mtdids variable not defined, using default\n");
			ids = mtdids_default;
			setenv("mtdids", (char *)ids);
		} else {
			printf("mtdids not defined, no default present\n");
			return 1;
		}
	}
        ... ...
}

    显然没有定义mtdids环境变量,ids为0,执行if (mtdids_default)语句,在同文件有如下定义:
    移植u-boot-2016.11到JZ2440(六:修改源码之环境变量、裁剪uboot与设置分区)

    我们的之前的各个配置文件默认没有定义MTDIDS_DEFAULT宏,所以执行mtdparts时输出错误信息,查看其它单板头文件是如何定义的,然后在include/configs/jz2440.h中修改添加如下代码:

/*
 * mtdparts
 */
#define CONFIG_CMD_MTDPARTS
#define CONFIG_MTD_DEVICE
#define MTDIDS_DEFAULT		"nand0=jz2440-0"  /* 哪一个设备 */
#define MTDPARTS_DEFAULT	"mtdparts=jz2440-0:256k(u-boot),"	\
						"128k(params),"		\
						"2m(kernel),"	        \
						"-(rootfs)"		\

    执行./remake.sh重新编译,烧写启动后进入uboot命令行执行“mtdparts default”命令时,uboot就会检测是否有CONFIG_CMD_MTDPARTS宏,然后再根据上面的MTDPARTS_DEFAULT宏保存的mtd分区信息,来将nand分区。再执行"mtdparts"如下:
    移植u-boot-2016.11到JZ2440(六:修改源码之环境变量、裁剪uboot与设置分区)
    下面修改代码,让uboot启动时自动设置分区(执行“mtdparts default”命令),在uboot进入main_loop()死循环之前添加执行命令代码(run_command("mtdparts default", 0);),修改run_main_loop()函数如下(common/board_r.c文件中):

static int run_main_loop(void)
{
#ifdef CONFIG_SANDBOX
	sandbox_main_loop_init();
#endif
        run_command("mtdparts default", 0);    /* 执行"mtdparts default"命令 */
	/* main_loop() can return to retry autoboot, if so just run it again */
	for (;;)
		main_loop();
	return 0;
}

    执行./remake.sh重新编译,新uboot启动时就会自动设置分区了。

6.2.2 使用分区名烧写文件

    以前的uboot烧写uImage
        tftp 30000000 uImage
        nand erase 60000 200000
        nand write 30000000 60000 200000

    现在uboot烧写uImage还可以使用:
        tftp 30000000 uImage
        nand erase.part kernel
        nand write 30000000 kernel

6.3 环境变量

6.3.1 修改默认环境变量

    修改完的uboot启动后执行print命令如下:
    移植u-boot-2016.11到JZ2440(六:修改源码之环境变量、裁剪uboot与设置分区)
    可以看到一些默认的环境变量,下面看看这些环境变量是在哪里调用输出的。首先定位“using default environment”是在set_default_env()函数里打印的,该函数代码如下(common/env_common.c文件)

void set_default_env(const char *s)
{
	int flags = 0;

	if (sizeof(default_environment) > ENV_SIZE) {
		puts("*** Error - default environment is too large\n\n");
		return;
	}

	if (s) {
		if (*s == '!') {
			printf("*** Warning - %s, "
				"using default environment\n\n",
				s + 1);
		} else {
			flags = H_INTERACTIVE;
			puts(s);
		}
	} else {
		puts("Using default environment\n\n");
	}

	if (himport_r(&env_htab, (char *)default_environment,
			sizeof(default_environment), '\0', flags, 0,
			0, NULL) == 0)
		error("Environment import failed: errno = %d\n", errno);

	gd->flags |= GD_FLG_ENV_READY;
	gd->flags |= GD_FLG_ENV_DEFAULT;
}

    default_environment是个全局字符数组,这就是是默认环境变量数组,里面保存了各个环境值,部分如下:
    移植u-boot-2016.11到JZ2440(六:修改源码之环境变量、裁剪uboot与设置分区)

    所以只需要修改相关宏就能修改默认环境变量了,网卡相关宏定义在include/configs/jz2440.h文件中,修改如下内容:
    移植u-boot-2016.11到JZ2440(六:修改源码之环境变量、裁剪uboot与设置分区)
    改为:

#define CONFIG_BOOTARGS  "console=ttySAC0 root=/dev/mtdblock3"
#define CONFIG_BOOTCOMMAND  "nand read 30000000 kernel;bootm 30000000"
#define CONFIG_ETHADDR 	00:0c:29:f2:9f:35
#define CONFIG_NETMASK		255.255.255.0
#define CONFIG_IPADDR		192.168.1.17
#define CONFIG_SERVERIP		192.168.1.12

    执行./remake.sh重新编译,烧写启动新uboot时就会默认使用上面的环境变量,不需要每次启动都去修改变量了。

6.3.2 修改支持保存环境变量

    如果想修改环境变量,而又不想修改源码,可以在命令行设置环境变量后,执行“save”命令保存,但是有如下输出:
    移植u-boot-2016.11到JZ2440(六:修改源码之环境变量、裁剪uboot与设置分区)
    在源码搜索“saveenv”如下:
    移植u-boot-2016.11到JZ2440(六:修改源码之环境变量、裁剪uboot与设置分区)

    可以看到有保存环境变量的许多文件,我们可以查看common目录下哪些文件被编译了或者查看该目录下的Makefile,发现上面这些文件只有env_flash.c被编译进uboot了(Makefile里判断宏CONFIG_ENV_IS_IN_FLASH),而该文件的函数是操作NOR Flash的,也就是将环境变量保存在NOR Flash
    由于2440nand启动下是无法支持NOR Flash的,所以我们将环境变量保存到NAND Flash里的分区2,也就是要使用env_nand.c文件,修改单板保存环境变量相关宏内容(include/configs/jz2440.h)
    移植u-boot-2016.11到JZ2440(六:修改源码之环境变量、裁剪uboot与设置分区)
    改为如下env_nand.c里面查找到需要定义下面这些宏才能正确使用

#define CONFIG_ENV_IS_IN_NAND    //Makeflie里面编译env_nand.c的条件宏
#define CONFIG_ENV_OFFSET      0x00040000         //环境变量起始地址
#define CONFIG_ENV_SIZE        0x20000            //环境变量的大小(NAND Flash需要设置为块对齐大小)
#define CONFIG_ENV_RANGE       CONFIG_ENV_SIZE    //要擦除的环境变量的大小

    执行./remake.sh重新编译,烧写启动新uboot,测试如下:
    移植u-boot-2016.11到JZ2440(六:修改源码之环境变量、裁剪uboot与设置分区)
    执行save命令就会把之前set的内容保存到NAND Flash里的分区2里了,以后重启开发板都会使用新保存的环境变量。