👹
Carlos's Tech Blog
  • 🧔ECUs
    • ZYNQ_Documents
      • [ZYNQ] 构建ZYNQ的BSP工程
      • [ZYNQ] 启动流程
      • [ZYNQ] Secure Boot Flow
      • [ZYNQ] Provisioning Guideline
      • [ZYNQ] Decrypting Partition by the Decrypt Agent Using PUF key
      • [ZYNQ] enabling the cryptsetup on ramdisk
      • [ZYNQ] Encrypt external files based on file system using PUF key
      • [ZYNQ] Loading an Encrypted Linux kernel at U-Boot with a KUP Key
      • [ZYNQ] cross-compile the cryptsetup on Xilinx ZYNQ aarch64 platform
      • [ZYNQ] Linux Linaro系统镜像制作SD卡启动
    • S32G_Documents
      • [S32G] Going through the s32g hard/soft platform
      • [S32G] S32g247's Secure Boot using HSE firmware
        • S32g2 HSE key config
        • How S32g verify secure boot image
        • S32g secure boot signature generation
        • How to download and build S32g Secure boot image
        • [S32G] OTA with Secure Boot
    • RT117x_Documents
      • [RT-117x]IMX RT1170 Provisioning Guideline
      • [RT-117x] Going through the MX-RT1170 hard/soft platform
      • [RT-117x] i.MX-RT1170's Secure Boot
        • [RT-117x]Signing image with the HSM (SignServer)
    • LS104x_Documents
      • [LS104x] bsp project
      • [LS104x] boot flow
      • [LS104x] secure boot
      • [LS104x] Application Note, Using the PKCS#11 in TCU platform
      • [LS104x] 使用ostree更新rootfs
      • [LS104x] ostree的移植
      • [LS104x] Starting with Yocto
      • [LS104x] 使用FIT的kernel格式和initramfs
    • IMX6/8_Documents
      • [IMX6] Defining A U-Boot Command
      • NXP IMX6 嵌入式板子一些笔记
      • NXP-imx6 initialization
    • Vehicle_Apps
      • [SecOC] Tree
        • [SecOC] SecOC Freshness and MAC Truncation
  • 😾TECH
    • Rust Arm OS
      • ARMv7m_Using_The_RUST_Cross_Compiler
    • ARM
      • ARM-v7-M
        • 01_ARMv7-M_处理器架构技术综述
        • 02_ARMv7-M_编程模型与模式
        • 03_ARMv7-M_存储系统结构
        • 04_ARMv7-M_异常处理及中断处理
      • ARM-v8-A
        • 02_ARMv8_基本概念
        • 03_ARMv8_指令集介绍_加载指令集和存储指令集
        • 04_ARMv8_指令集_运算指令集
        • 05_ARMv8_指令集_跳转_比较与返回指令
        • 06_ARMv8_指令集_一些重要的指令
        • 0X_ARMv8_指令集_基于汇编的UART驱动
        • 07_ARMv8_汇编器Using as
        • 08_ARMv8_链接器和链接脚本
        • 09_ARMv8_内嵌汇编(内联汇编)Inline assembly
        • 10_ARMv8_异常处理(一) - 入口与返回、栈选择、异常向量表
        • 11_ARMv8_异常处理(二)- Legacy 中断处理
        • 12_ARMv8_异常处理(三)- GICv1/v2中断处理
        • 13_ARMv8_内存管理(一)-内存管理要素
        • 14_ARMv8_内存管理(二)-ARM的MMU设计
        • 15_ARMv8_内存管理(三)-MMU恒等映射及Linux实现
        • 16_ARMv8_高速缓存(一)cache要素
        • 17_ARMv8_高速缓存(二)ARM cache设计
        • 18_ARMv8_高速缓存(三)多核与一致性要素
        • 19_ARMv8_TLB管理(Translation Lookaside buffer)
        • 20_ARMv8_barrier(一)流水线和一致性模型
        • 21_ARMv8_barrier(二)内存屏障案例
      • ARM Boot Flow
        • 01_Embedded_ARMv7/v8 non-secure Boot Flow
        • 02_Embedded_ARMv8 ATF Secure Boot Flow (BL1/BL2/BL31)
        • 03_Embedded_ARMv8 BL33 Uboot Booting Flow
      • ARM Compiler
        • Compiler optimization and the volatile keyword
      • ARM Development
        • 在MACBOOK上搭建ARMv8架构的ARM开发环境
        • Starting with JLink debugger or QEMU
    • Linux
      • Kernel
        • 0x01_LinuxKernel_内核的启动(一)之启动前准备
        • 0x02_LinuxKernel_内核的启动(二)SMP多核处理器启动过程分析
        • 0x21_LinuxKernel_内核活动(一)之系统调用
        • 0x22_LinuxKernel_内核活动(二)中断体系结构(中断上文)
        • 0x23_LinuxKernel_内核活动(三)中断体系结构(中断下文)
        • 0x24_LinuxKernel_进程(一)进程的管理(生命周期、进程表示)
        • 0x25_LinuxKernel_进程(二)进程的调度器的实现
        • 0x26_LinuxKernel_设备驱动(一)综述与文件系统关联
        • 0x27_LinuxKernel_设备驱动(二)字符设备操作
        • 0x28_LinuxKernel_设备驱动(三)块设备操作
        • 0x29_LinuxKernel_设备驱动(四)资源与总线系统
        • 0x30_LinuxKernel_设备驱动(五)模块
        • 0x31_LinuxKernel_内存管理(一)物理页面、伙伴系统和slab分配器
        • 0x32_LinuxKernel_内存管理(二)虚拟内存管理、缺页与调试工具
        • 0x33_LinuxKernel_同步管理_原子操作_内存屏障_锁机制等
        • 01_LinuxDebug_调试理论和基础综述
      • Userspace
        • Linux-用户空间-多线程与同步
        • Linux进程之间的通信-管道(上)
        • Linux进程之间的通信-管道(下)
        • Linux进程之间的通信-信号量(System V)
        • Linux进程之间的通信-内存共享(System V)
        • Linux进程之间的通信-消息队列(System V)
        • Linux应用调试(一)方法、技巧和工具 - 综述
        • Linux应用调试(二)工具之coredump
        • Linux应用调试(三)工具之Valgrind
        • Linux机制之内存池
        • Linux机制之对象管理和引用计数(kobject/ktype/kset)
        • Linux机制copy_{to, from}_user
        • Linux设备树 - DTS语法、节点、设备树解析等
        • Linux System : Managing Linux Services - inittab & init.d
        • Linux System : Managing Linux Services - initramfs
      • Kernel Examples
        • Linux Driver - GPIO键盘驱动开发记录_OMAPL138
        • 基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(一)之miscdevice和ioctl
        • 基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(二)之cdev与read、write
        • 基于OMAPL138的字符驱动_GPIO驱动AD9833(三)之中断申请IRQ
        • Linux内核调用SPI驱动_实现OLED显示功能
        • Linux内核调用I2C驱动_驱动嵌套驱动方法MPU6050
    • OPTEE
      • 01_OPTEE-OS_基础之(一)功能综述、简要介绍
      • 02_OPTEE-OS_基础之(二)TrustZone和ATF功能综述、简要介绍
      • 03_OPTEE-OS_系统集成之(一)编译、实例、在QEMU上执行
      • 05_OPTEE-OS_系统集成之(三)ATF启动过程
      • 06_OPTEE-OS_系统集成之(四)OPTEE镜像启动过程
      • 07_OPTEE-OS_系统集成之(五)REE侧上层软件
      • 08_OPTEE-OS_系统集成之(六)TEE的驱动
      • 09_OPTEE-OS_内核之(一)ARM核安全态和非安全态的切换
      • 10_OPTEE-OS_内核之(二)对安全监控模式的调用的处理
      • 11_OPTEE-OS_内核之(三)中断与异常的处理
      • 12_OPTEE-OS_内核之(四)对TA请求的处理
      • 13_OPTEE-OS_内核之(五)内存和cache管理
      • 14_OPTEE-OS_内核之(六)线程管理与并发
      • 15_OPTEE-OS_内核之(七)系统调用及IPC机制
      • 16_OPTEE-OS_应用之(一)TA镜像的签名和加载
      • 17_OPTEE-OS_应用之(二)密码学算法和安全存储
      • 18_OPTEE-OS_应用之(三)可信应用的开发
      • 19_OPTEE-OS_应用之(四)安全驱动开发
      • 20_OPTEE-OS_应用之(五)终端密钥在线下发系统
    • Binary
      • 01_ELF文件_目标文件格式
      • 02_ELF文件结构_浅析内部文件结构
      • 03_ELF文件_静态链接
      • 04_ELF文件_加载进程虚拟地址空间
      • 05_ELF文件_动态链接
      • 06_Linux的动态共享库
      • 07_ELF文件_堆和栈调用惯例以ARMv8为例
      • 08_ELF文件_运行库(入口、库、多线程)
      • 09_ELF文件_基于ARMv7的Linux系统调用原理
      • 10_ELF文件_ARM的镜像文件(.bin/.hex/.s19)
    • Build
      • 01_Script_makefile_summary
    • Rust
      • 02_SYS_RUST_文件IO
    • Security
      • Crypto
        • 1.0_Security_计算机安全概述及安全需求
        • 2.0_Security_随机数(伪随机数)
        • 3.0_Security_对称密钥算法加解密
        • 3.1_Security_对称密钥算法之AES
        • 3.2_Security_对称密钥算法之MAC(CMAC/HMAC)
        • 3.3_Security_对称密钥算法之AEAD
        • 8.0_Security_pkcs7(CMS)_embedded
        • 9.0_Security_pkcs11(HSM)_embedded
      • Tools
        • Openssl EVP to implement RSA and SM2 en/dec sign/verify
        • 基于Mac Silicon M1 的OpenSSL 编译
        • How to compile mbedtls library on Linux/Mac/Windows
    • Embedded
      • eMMC启动介质
  • 😃Design
    • Secure Boot
      • JY Secure Boot Desgin
    • FOTA
      • [FOTA] Module of ECUs' FOTA unit design
        • [FOTA] Tech key point: OSTree Deployment
        • [FOTA] Tech key point: repositories role for onboard
        • [FOTA] Tech key point: metadata management
        • [FOTA] Tech key point: ECU verifying and Decrpting
        • [FOTA] Tech key point: time server
      • [FOTA] Local-OTA for Embedded Linux System
    • Provisioning
      • [X-Shield] Module of the Embedded Boards initialization
    • Report
由 GitBook 提供支持
在本页
  • 1. Function Overview
  • 2. U-Boot independent APP
  • 2.1 Code Base
  • 2.2 Judging Secure Boot
  • 3. Examples
  • 3.1 BEE
  • 3.2 Control LEDs
  • 3.3 movi
  • 3.4 uboot env copying
  1. ECUs
  2. IMX6/8_Documents

[IMX6] Defining A U-Boot Command

Compiling a user uboot command

上一页IMX6/8_Documents下一页NXP IMX6 嵌入式板子一些笔记

最后更新于1年前

1. Function Overview

I wish to boot a partition that can be decided in the U-Boot stage. The process is highlighted below:

I have to compose the U-Boot independent application to implement the logic marked red.

2. U-Boot independent APP

The U-Boot provides a console we can interact with. This section will introduce how to add an independent command to the U-Boot source code project. In the U-Boot project, each U-Boot provided command is defined by U_BOOT_CMD macro in include/command.h.

#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \

cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage}

Attributes:

  • name: The command name;

  • maxargs: The maximum of the inputted arguments;

  • command: The C function is mapped to the command;

  • usage: Usage message;

  • ...

2.1 Code Base

Assuming the command name is utils_load

Add obj-y += utils_load.o to Makefile in common directory.

Create utils_load.c file in common directory.

The content of utils_load.c file is:

#include <common.h>
#include <command.h>
#include <linux/stddef.h>

int do_utils_load(cmd_tbl_t *cmdtp, int flag, int argc, char* const argv[])
{
    int ret = 0;
    int i = 0;

    printf("[INFO] The input is %d\n", argc);
    for (i = 0; i < argc; i ++) {
        printf("[INFO] the argv[%d] is %s\n", i, argv[i]);
    }

finish:
    return ret;
}

U_BOOT_CMD(
    utils_load,
    5,
    1,
    do_utils_load,
    "format : utils_load address",
    "example: utils_load 0x80000000"
);

Then build the U-Boot by

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16

in imx6 platform.

2.2 Judging Secure Boot

There are two versions of NXP S32G SoC:

  • Rev 1.0

  • Rev 2.0 (The HSE is enabled)

The Rev 1.0 hasn't HSE, while the Rev 2.0 has enabled the HSE.

We can use the version information to distinguish if the SoC has been enabled HSE.

The Secure Boot can be distinguished by DDR storage:

3. Examples

3.1 BEE

#include <common.h>
#include <command.h>
#define GPD0CON		(*(volatile unsigned int *)0x114000A0) //定义蜂鸣器IO口的地址
#define GPD0DAT		(*(volatile unsigned int *)0x114000A4)

int do_beep( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	GPD0CON&=~(0xf<<0);
	GPD0CON|=(0x1<<0);
	
	if(!strcmp(argv[1],"on"))  //strcmp是比较字符串的函数,如果传进来的是on,就打开蜂鸣器
		{
			GPD0DAT|=(1<<0);	
		}
	if(!strcmp(argv[1],"off"))//strcmp是比较字符串的函数,如果传进来的是off,就关闭蜂鸣器
		{
		 	GPD0DAT&=~(1<<0);	
		}
	else
		printf("Usage:beep <on|off>!\n"); //如果不是on 也不是off  就输出提示
}


U_BOOT_CMD( 
	beep,    //在u-boot命令行里显示的命令名称
	2,       //形参最大个数
	1,       //重复次数 (按下回车--自动执行上一次命令)
	do_beep, //命令执行函数(回调函数--)
	"传参格式: beep <on|off>",   //用法提示
	"传承示例:beep on 或者 beep off......."  //帮助命令的提示信息
);

3.2 Control LEDs

#include <common.h>
#include <command.h>

/* 1、LED灯接口配置寄存器 */
#define GPM4CON     (*(volatile unsigned int *)0x110002E0)
#define GPM4DAT     (*(volatile unsigned int *)0x110002E4)

int do_led(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	// led 1 on
	// led 1 off
	GPM4CON &= ~(0xf << 0 * 4);    //清除寄存器1
  GPM4CON |=  (1   << 0 * 4);    //输出模式
  
  GPM4CON &= ~(0xf << 1 * 4);    //清除寄存器2
  GPM4CON |=  (1   << 1 * 4);    //输出模式
  
  GPM4CON &= ~(0xf << 2 * 4);    //清除寄存器3
  GPM4CON |=  (1   << 2 * 4);    //输出模式
  
  GPM4CON &= ~(0xf << 3 * 4);    //清除寄存器4
  GPM4CON |=  (1   << 3 * 4);    //输出模式
  
  
  /*第一盏灯*/	
	if(!strcmp(argv[1],"1"))  //strcmp是比较字符串的函数,如果传进来的是on,就打开蜂鸣器
		{
			if(!strcmp(argv[2],"on"))
			{
				GPM4DAT &= ~(1 << 0);      //点亮第一个灯 
			}
			else if(!strcmp(argv[2],"off"))
			{
				GPM4DAT |=1 << 0;          //关闭第一个灯 
			}
		}
		
		/*第二盏灯*/	
	else if(!strcmp(argv[1],"2"))  //strcmp是比较字符串的函数,如果传进来的是on,就打开蜂鸣器
		{
			if(!strcmp(argv[2],"on"))
			{
				GPM4DAT &= ~(1 << 1);      //点亮第二个灯 
			}
			else if(!strcmp(argv[2],"off"))
			{
				GPM4DAT |=1 << 1;          //关闭第二个灯 
			}
		}
	
		/*第三盏灯*/	
	else if(!strcmp(argv[1],"3"))  //strcmp是比较字符串的函数,如果传进来的是on,就打开蜂鸣器
		{
			if(!strcmp(argv[2],"on"))
			{
				GPM4DAT &= ~(1 << 2);      //点亮第三个灯 
			}
			else if(!strcmp(argv[2],"off"))
			{
				GPM4DAT |=1 << 2;          //关闭第三个灯 
			}
		}
		
	/*第四盏灯*/	
	else if(!strcmp(argv[1],"4"))  //strcmp是比较字符串的函数,如果传进来的是on,就打开蜂鸣器
		{
			if(!strcmp(argv[2],"on"))
			{
				GPM4DAT &= ~(1 << 3);      //点亮第四个灯 
			}
			else if(!strcmp(argv[2],"off"))
			{
				GPM4DAT |=1 << 3;          //关闭第四个灯 
			}
		}

	else
		printf("Usage:led <1~4> <on|off>\n"); //如果不是on 也不是off  就输出提示
}


U_BOOT_CMD( 
	led,     //在u-boot命令行里显示的命令名称
	3,       //形参最大个数
	1,       //重复次数
	do_led,  //命令执行函数
	"user: LED count <on|off>",   //用法提示
	"cmd : (1)led  1 on (2)led 1 off...."  //帮助命令的提示信息
);

3.3 movi

#include <common.h>
#include <command.h>
#include <environment.h>
#include <linux/stddef.h>
#include <malloc.h>
#include <nand.h>
#include <onenand_uboot.h>
#include <mmc.h>
#include <asm/arch/cpu.h>
#include <asm/arch/movi_partition.h>

int do_mymovi(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
	int r_cnt,w_cnt;
   /*1. 查找设备0-SD卡*/
	struct mmc *mmc0 = find_mmc_device(0);
	if(mmc0==NULL)
	{
		printf("设备0查找失败!\n");
		return 0;
	}
	/*2. 查找设备1--MMC*/
	struct mmc *mmc1 = find_mmc_device(1);
	if(mmc1==NULL)
	{
		printf("设备1查找失败!\n");
		return 0;
	}
	/*3. 初始化SD卡*/
    mmc_init(mmc0); /*设备0初始化--SD卡*/
  
  /*4. 初始化EMMC*/
  	mmc_init(mmc1); /*设备1初始化--EMMC卡*/ 
	emmc_boot_open(mmc1); /*设备1打开---EMMC*/
	
	/*5. 烧写数据*/
		/*5.1 BL1*/
		r_cnt=movi_read(0,1,16,(void*)0x40008000); //读出SD卡里存放到所有数据到DDR指定地址
		w_cnt=movi_write(1,0,16,(void*)0x40008000);//将读出的数据写入到EMMC
		printf("BL1_r_cnt=%d\n",r_cnt);
		printf("BL1_w_cnt=%d\n",w_cnt);
  	
  	/*5.2 BL2*/
  	    r_cnt=movi_read(0,17,32,(void*)0x40008000); //读出SD卡里存放到所有数据到DDR指定地址
		w_cnt=movi_write(1,16,32,(void*)0x40008000);//将读出的数据写入到EMMC
		printf("BL2_r_cnt=%d\n",r_cnt);
		printf("BL2_w_cnt=%d\n",w_cnt);

	  /*5.3 UBOOT\这里最好使用malloc申请空间,太大的地址可能会被其他数据覆盖掉*/
  		r_cnt=movi_read(0,49,656,(void*)0x40008000); //读出SD卡里存放到所有数据到DDR指定地址
		w_cnt=movi_write(1,48,656,(void*)0x40008000);//将读出的数据写入到EMMC
		printf("UBOOT_r_cnt=%d\n",r_cnt);
		printf("UBOOT_w_cnt=%d\n",w_cnt);
		
		/*5.4 TZSW*/
  		r_cnt=movi_read(0,705,320,(void*)0x40008000); //读出SD卡里存放到所有数据到DDR指定地址
		w_cnt=movi_write(1,704,320,(void*)0x40008000);//将读出的数据写入到EMMC
		printf("TZSW_r_cnt=%d\n",r_cnt);
		printf("TZSW_w_cnt=%d\n",w_cnt);
		
		/*5.5 Linux内核*/
  		r_cnt=movi_read(0,1057,12288,(void*)0x40008000); //读出SD卡里存放到所有数据到DDR指定地址
		w_cnt=movi_write(1,1057,12288,(void*)0x40008000);//将读出的数据写入到EMMC
		printf("Linux内核_r_cnt=%d\n",r_cnt);
		printf("Linux内核_w_cnt=%d\n",w_cnt);
  	emmc_boot_close(mmc1); //关闭EMMC
	
	/*5.5 环境变量*/
	r_cnt=movi_read(0,1025,32,(void*)0x40008000); //读出SD卡里存放到所有数据到DDR指定地址
	w_cnt=movi_write(1,1025,32,(void*)0x40008000);//将读出的数据写入到EMMC
	printf("环境变量_r_cnt=%d\n",r_cnt);
	printf("环境变量_w_cnt=%d\n",w_cnt);
	printf("环境变量拷贝成功!\n");
	return 0;
}

U_BOOT_CMD(
	mymovi,    /*命令的名称*/
	1,          /*形参的最大个数*/
	0,          /*命令执行重复次数*/
	do_mymovi,/*命令处理函数*/
	"将SD卡的BL1/BL2/uboot/签名文件/内核拷贝到EMMC", /*简短提示*/
	"\n"
	"将SD卡的BL1/BL2/uboot/签名文件/内核拷贝到EMMC\n" /*完整提示*/
	"注意: 该命令在开发板以SD卡启动方式时运用\n"
);

3.4 uboot env copying

#include <common.h>
#include <command.h>
#include <environment.h>
#include <linux/stddef.h>
#include <malloc.h>
#include <nand.h>
#include <onenand_uboot.h>
#include <mmc.h>
#include <asm/arch/cpu.h>
#include <asm/arch/movi_partition.h>

/*
//以MMC方式启动,运行下面命令即可完成环境变量拷贝(SD-->EMMC)
mmc read 1 40000000 401 20
mmc write 0 40000000 401 20

//以SD方式启动,运行下面命令即可完成环境变量拷贝 (SD--->EMMC)
mmc read 0 40000000 401 20
mmc write 1 40000000 401 20
*/
int do_copyenv(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
	int r_cnt,w_cnt;
    mmc_init(find_mmc_device(0)); /*设备0初始化--SD卡*/
  	mmc_init(find_mmc_device(1)); /*设备1初始化--EMMC卡*/ 

	/*5.5 环境变量*/
	r_cnt=movi_read(0,1025,32,(void*)0x40000000); //读出SD卡里存放到所有数据到DDR指定地址
	w_cnt=movi_write(1,1025,32,(void*)0x40000000);//将读出的数据写入到EMMC
	printf("环境变量_r_cnt=%d\n",r_cnt);
	printf("环境变量_w_cnt=%d\n",w_cnt);
	printf("环境变量拷贝成功!\n");
	return 0;
}


U_BOOT_CMD(
	copyenv,    /*命令的名称*/
	1,          /*形参的最大个数*/
	0,          /*命令执行重复次数*/
	do_copyenv,/*命令处理函数*/
	"将SD卡的环境变量拷贝到EMMC", /*简短提示*/
	"\n"
	"将SD卡的环境变量拷贝到EMMC\n" /*完整提示*/
	"注意: 该命令在开发板以SD卡启动方式时运用\n"
);

Here are some examples of common U-Boot independent applications at

🧔
https://github.com/carloscn/imx-uboot/commit/916419376b988d1a16461810bf358f94ca990e0f#diff-d397fabf5af5abbfeebdcba5c3b68879fb33e5bd432ea70a75e26dbf850a848b
https://cloud.tencent.com/developer/article/1974907
without HSE booting log
with HSE booting log