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
写号工具
源码
环境变量的实现中,分多层实现, 从下往上:存储驱动层-》中间维护层-》命令访问层。
- 存储驱动层实现统一的存储访问接口,供中间维护层;
- 中间维护层负责维护加载到内存中的环境变量;
- 命令访问层由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);
}