T113 序列号

U-boot

Posted by LXG on November 18, 2023

U-boot 日志打印

【FAQ1104】 Tina-启动过程信息打印

./device/config/chips/t113/configs/evb1/uboot-board.dts

env.cfg

内核从U-boot获取snum参数

./device/config/chips/t113/configs/evb1_auto/longan/env.cfg


#kernel command arguments
earlycon=uart8250,mmio32,0x05000000
initcall_debug=0
console=ttyS0,115200
nand_root=ubi0_5
mmc_root=/dev/mmcblk0p5
mtd_name=sys
rootfstype=ubifs,rw
init=/init
loglevel=8
cma=16M
mac=
wifi_mac=
bt_mac=
specialstr=
keybox_list=widevine,ec_key,ec_cert1,ec_cert2,ec_cert3,rsa_key,rsa_cert1,rsa_cert2,rsa_cert3
dsp0_partition=dsp0
#set kernel cmdline if boot.img or recovery.img has no cmdline we will use this
setargs_nand=setenv bootargs ubi.mtd=${mtd_name} earlycon=${earlycon} clk_ignore_unused initcall_debug=${initcall_debug} console=${console} loglevel=${loglevel} root=${nand_root} rootfstype=${rootfstype} init=${init} partitions=${partitions} cma=${cma} snum=${snum} mac_addr=${mac} wifi_mac=${wifi_mac} bt_mac=${bt_mac} specialstr=${specialstr} gpt=1


setargs_nand_ubi=setenv bootargs ubi.mtd=${mtd_name} earlycon=${earlycon} clk_ignore_unused initcall_debug=${initcall_debug} console=${console} loglevel=${loglevel} root=${nand_root} rootfstype=${rootfstype} init=${init} partitions=${partitions} cma=${cma} snum=${snum} mac_addr=${mac} wifi_mac=${wifi_mac} bt_mac=${bt_mac} specialstr=${specialstr} gpt=1


setargs_mmc=setenv  bootargs earlycon=${earlycon} clk_ignore_unused initcall_debug=${initcall_debug} console=${console} loglevel=${loglevel} root=${mmc_root}  init=${init} partitions=${partitions} cma=${cma} snum=${snum} mac_addr=${mac} wifi_mac=${wifi_mac} bt_mac=${bt_mac} specialstr=${specialstr} gpt=1


#nand command syntax: sunxi_flash read address partition_name read_bytes
#0x4007f800 = 0x40080000(kernel entry) - 0x800(boot.img header 2k)
boot_dsp0=sunxi_flash read 43000000 ${dsp0_partition};bootr 43000000 0 0
boot_normal=sunxi_flash read 43000000 boot;bootm 43000000
boot_recovery=sunxi_flash read 43000000 recovery;bootm 43000000
boot_fastboot=fastboot

#uboot system env config
bootdelay=0
#default bootcmd, will change at runtime according to key press
#default nand boot
bootcmd=run setargs_mmc boot_dsp0 boot_normal


env 命令

ADB


sh-4.4# env
boot_type=2
disp_reserve=4096000,0x448ec000
snum=Q1SAM00000000001
earlycon=uart8250,mmio32,0x05000000
bt_mac=
USER=root
PWD=/
HOME=/
uboot_message=2018.05(11/17/2023-10:10:11)
SHELL=/bin/sh
TERM=vt102
SHLVL=3
specialstr=
partitions=boot-resource@mmcblk0p1:env@mmcblk0p2:env-redund@mmcblk0p3:boot@mmcblk0p4:rootfs@mmcblk0p5:dsp0@mmcblk0p6:private@mmcblk0p7:UDISK@mmcblk0p8
PATH=/sbin:/usr/sbin:/bin:/usr/bin
wifi_mac=
mac_addr=
_=/usr/bin/env

串口


LD_LIBRARY_PATH=/usr/local/Qt_5.12.5/lib:/usr/lib/cedarx/:
QWS_MOUSE_PROTO=
boot_type=2
QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event5
QTDIR=/usr/local/Qt_5.12.5
disp_reserve=4096000,0x448ec000
snum=Q1SAM00000000001
EDITOR=/bin/vi
QT_QPA_FONTDIR=/usr/local/Qt_5.12.5/fonts
earlycon=uart8250,mmio32,0x05000000
bt_mac=
USER=root
PAGER=/bin/more
QT_QPA_PLATFORM_PLUGIN_PATH=/usr/local/Qt_5.12.5/plugins
PWD=/
HOME=/
QT_QPA_GENERIC_PLUGINS=evdevtouch
uboot_message=2018.05(11/17/2023-10:10:11)
QT_ROOT=/usr/local/Qt_5.12.5
SHELL=/bin/sh
TERM=vt102
SHLVL=1
specialstr=
QT_QPA_PLATFORM=linuxfb:rotation=90
XDG_RUNTIME_DIR=/dev/shm
partitions=boot-resource@mmcblk0p1:env@mmcblk0p2:env-redund@mmcblk0p3:boot@mmcblk0p4:rootfs@mmcblk0p5:dsp0@mmcblk0p6:private@mmcblk0p7:UDISK@mmcblk0p8
PATH=/usr/local/Qt_5.12.5/bin:/bin:/sbin:/usr/bin:/usr/sbin
PS1=#
wifi_mac=
mac_addr=
_=/usr/bin/env

写号工具

dragon_sn

源码

环境变量的实现中,分多层实现, 从下往上:存储驱动层-》中间维护层-》命令访问层。

  1. 存储驱动层实现统一的存储访问接口,供中间维护层;
  2. 中间维护层负责维护加载到内存中的环境变量;
  3. 命令访问层由U-boot几条环境变量相关的命令printenv,savenv等组成,对环境变量进行访问。

在中间维护层和命令访问层之间,为不同类型变量值提供不同访问接口。


t113_linux/brandy/brandy-2.0/u-boot-2018/env$ tree
.
├── attr.c
├── callback.c
├── common.c
├── eeprom.c
├── embedded.c
├── env.c
├── ext4.c
├── fat.c
├── flags.c
├── flash.c
├── Kconfig
├── Makefile
├── mmc.c
├── nand.c
├── nowhere.c
├── nvram.c
├── onenand.c
├── remote.c
├── sata.c
├── sf.c
├── sunxi_flash.c
└── ubi.c

存储驱动层

include/environment.h


struct env_driver {
	const char *name;
	enum env_location location;

	/**
	 * load() - Load the environment from storage
	 *
	 * This method is optional. If not provided, no environment will be
	 * loaded.
	 *
	 * @return 0 if OK, -ve on error
	 */
	int (*load)(void);

	/**
	 * save() - Save the environment to storage
	 *
	 * This method is required for 'saveenv' to work.
	 *
	 * @return 0 if OK, -ve on error
	 */
	int (*save)(void);

	/**
	 * init() - Set up the initial pre-relocation environment
	 *
	 * This method is optional.
	 *
	 * @return 0 if OK, -ENOENT if no initial environment could be found,
	 * other -ve on error
	 */
	int (*init)(void);
};


/**
 * 加载环境变量到内存
 * env_load() - Load the environment from storage
 *
 * @return 0 if OK, -ve on error
 */
int env_load(void);

/**
 * 保存内存中的环境变量到非易失存储设备
 * env_save() - Save the environment to storage
 *
 * @return 0 if OK, -ve on error
 */
int env_save(void);


CONFIG_ENV_IS_IN_SUNXI_FLASH

u-boot-2018/.config:CONFIG_ENV_IS_IN_SUNXI_FLASH=y

./cmd/sunxi_flash.c ./drivers/sunxi_flash/sunxi_flash.c ./env/sunxi_flash.c


static inline int read_env(struct blk_desc *desc, uint blk_cnt, uint blk_start,
			   const void *buffer)
{
	uint n;

	n = blk_dread(desc, blk_start, blk_cnt, (uchar *)buffer);

	return (n == blk_cnt) ? 0 : -1;
}

命令访问层

cmd/nvedit.c


/*
 * Look up variable from environment,
 * return address of storage for that variable,
 * or NULL if not found
 */
char *env_get(const char *name)
{
	if (gd->flags & GD_FLG_ENV_READY) { /* after import into hashtable */
		ENTRY e, *ep;

		WATCHDOG_RESET();

		e.key	= name;
		e.data	= NULL;
		hsearch_r(e, FIND, &ep, &env_htab, 0);

		return ep ? ep->data : NULL;
	}

	/* restricted capabilities before import */
	if (env_get_f(name, (char *)(gd->env_buf), sizeof(gd->env_buf)) > 0)
		return (char *)(gd->env_buf);

	return NULL;
}

/*
 * Look up variable from environment for restricted C runtime env.
 */
int env_get_f(const char *name, char *buf, unsigned len)
{
	int i, nxt, c;

	for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
		int val, n;

		for (nxt = i; (c = env_get_char(nxt)) != '\0'; ++nxt) {
			if (c < 0)
				return c;
			if (nxt >= CONFIG_ENV_SIZE)
				return -1;
		}

		val = envmatch((uchar *)name, i);
		if (val < 0)
			continue;

		/* found; copy out */
		for (n = 0; n < len; ++n, ++buf) {
			c = env_get_char(val++);
			if (c < 0)
				return c;
			*buf = c;
			if (*buf == '\0')
				return n;
		}

		if (n)
			*--buf = '\0';

		printf("env_buf [%d bytes] too small for value of \"%s\"\n",
			len, name);

		return n;
	}

	return -1;
}


获取序列号的方法


#include <stdlib.h>

int main ()
{
    char *snum = getenv("snum");
    printf("snum--------------------:%s\n", snum);

}