【BSP开发经验】uboot gpl框架开发经验

文章目录

uboot_gpl 隔离 的目的

U-Boot 的 GPL 隔离是指在 U-Boot 中,将 GPL 认为具有侵权风险的代码与非 GPL 代码分隔开来,以避免 GPL 认为有侵权风险的代码"污染"了非 GPL 代码,从而使得整个 U-Boot 项目遵守 GPL 协议,保障代码的版权和使用权。 其主要作用如下:

  1. 保障代码的版权和使用权:U-Boot 作为开源软件,遵守 GPL 协议是其发展的基础,GPL 隔离可以使得 U-Boot 的使用和开发更加便捷和合法,同时也可以避免因 GPL 侵权而影响项目发展。
  2. 提高代码质量:执行 GPL 隔离可以使得开发者更加清晰地了解 U-Boot 中的 GPL 代码和非 GPL 代码,进而提高代码的可读性和可维护性。
  3. 提高代码的灵活性与可移植性:将 GPL 代码和非 GPL 代码分隔开来,有助于减少不同软件项目之间存在的依赖关系,从而增加了 U-Boot 的可移植性和灵活性,使得其更易于在不同的硬件平台和应用场景中使用和定制。

总之,U-Boot 的 GPL 隔离可以有效保障代码的版权和使用权,提高代码的质量和可维护性,增加了代码的灵活性和可移植性,使得整个项目更加健康、可持续发展

uboot_gpl 隔离基本原理

uboot gpl本质上是uboot中的standalone程序,也可以理解为独立的裸机代码。通过修改链接脚本指定代码段最开始的函数,uboot从flash中读入uboot_gpl镜像之后,只需要跳到这个镜像地址的位置,就可以直接运行指定在代码段最开始的函数。

链接脚本示例:

链接结果:

拼接方式:

uboot gpl镜像直接拼接在uboot镜像后面固定地址的位置,中间空出的地方用0x00 或者 0xff进行填充。这样uboot就可以直接算出gpl镜像在flash中的位置。

具体的计算方式可以使用:

uboot的起始偏移+uboot与gpl总镜像大小-gpl镜像大小

uboot_gpl 基本框架

uboot_gpl框架总体上可以分为四层,uboot运行层,hikcmd运行接口层,uboot_gpl运行支持层,uboot_gpl功能实现层。

uboot运行层是指uboot原始代码,是从芯片厂商哪里拿来的uboot的源码。

hikcmd运行支持层包含海康需要在原厂uboot添加的源码,以及运行gpl代码所需的代码。

uboot_gpl运行支持层包含一个小型的C库和一个命令分类器。命令分类器的作用就是通过hikcmd传入的功能参数,找到对应的uboot功能层提供的函数,以及传入uboot中传入的参数。

uboot_gpl功能层 ,需要进行gpl隔离的相关代码,目前包含psh,unpack等功能。

uboot_gpl 适配新平台的方式

uboot 添加hikcmd功能

为了可以调用gpl镜像,需要在uboot中添加hikuboot_gpl_init 功能 和 hikcmd 命令,hikuboot_gpl_init的作用是将uboot_gpl镜像读入内存,然后进行校验。hikcmd的作用是跳转到uboot_gpl镜像的开始位置并传入参数,其基本调用格式为:

hikcmd [load_addr] [function] [argv]

hikcmd 0x45000004 psh 0x%x 0x%x

适配调试步骤

到这里uboot gpl适配基本就完成了,适配完成后就可以将uboot.bin替代原有Uboot烧写到flash里面,这个时候可以尝试看看hikcmd能否调用gpl运行如果不行,需要检查原因。

可以尝试注掉main函数中所有内容,然后只有return , 然后看看uboot能否拿到这个return 的数值,如果数值返回异常说明调用异常。

如果有返回值,没有打印需要检查uboot提供的getc与putc是否正常。

链接脚本语法

链接脚本的格式

链接脚本是文本文件。你写一个链接脚本就是写一系列命令。每个命令要么是一个可能后面跟着参数的关键字,要么是对符号的赋值。命令可以用分号分隔。空格通常被忽略。

对于字符串,如文件或格式名称,通常可以直接放进去。如果文件名包含逗号等字符,由于这种符号会分隔文件名,为了避免被分隔,可以将文件名放在双引号中。不能在文件名中使用双引号字符。

你可以在链接脚本中包含注释,就像在C中一样,用 /* 和*/ 分隔。与C语言一样,注释在语法上等同于空格。

链接脚本的简单示例

许多链接脚本都相当简单。最简单的链接脚本只有一个命令:' SECTIONS '。可以使用' SECTIONS '命令来描述输出文件的内存布局。SECTIONS命令是一个功能强大的命令。这里我们将描述它的一个简单用法。让我们假设程序只由代码、初始化数据和未初始化数据组成。它们将分别在' .text '、' .data '和' .bss '区域中。让我们进一步假设这些节是在输入文件中出现的唯一的节,没有其他节。对于这个例子,假设代码应该在地址' 0x10000000'加载,并且数据应该从地址' 0x30000000'开始。下面的链接脚本将实现该功能

SECTIONS
{
    . = 0x10000000;
    .text : { *(.text) }
    . = 0x30000000;
    .data ALIGN(4) : { *(.data) }
    .bss ALIGN(4) : { *(.bss) }
}

第 1 行我们先写了一个关键字"SECTIONS",后面跟了一个大括号,这个大括号和第 7 行的大括号是一对,这是必须的。看起来就跟 C 语言里面的函数一样。

第 2 行对一个特殊符号"."进行赋值,"."在链接脚本里面叫做定位计数器,默认的定位计数器为 0。我们要求代码链接到以 0X10000000 为起始地址的地方,因此这一行给"."赋值0X10000000,表示以 0X10000000 开始,后面的文件或者段都会以 0X10000000 为起始地址开始链接。

第 3 行的".text"是段名(代码段),后面的冒号是语法要求,冒号后面的大括号里面可以填上要链接到".text"这个段里面的所有文件,"(.text)"中的""是通配符,表示所有输入文件的.text段都放到".text"中。

第 4 行,我们的要求是数据放到 0X30000000 开始的地方,所以我们需要重新设置定位计数器".",将其改为 0X30000000。如果不重新设置的话会怎么样?假设".text"段大小为 0X10000,那么接下来的.data 段开始地址就是 0X10000000+0X10000=0X10010000,这明显不符合我们的要求。所以我们必须调整定位计数器为 0X30000000。

第 5 行跟第 3 行一样,定义了一个名为".data"的段(数据段),然后所有文件的".data"段都放到这里面。但是这一行多了一个"ALIGN(4)",这是什么意思呢?这是用来对".data"这个段的起始地址做字节对齐的, ALIGN(4)表示 4 字节对齐。也就是说段".data"的起始地址要能被 4 整除,一般常见的都是 ALIGN(4)或者 ALIGN(8),也就是 4 字节或者 8 字节对齐。

第 6 行定义了一个".bss"段(bss数据段x,表示定义了但是还没有初始化的数据段),所有文件中的".bss"数据都会被放到这个里面,".bss"数据就是那些定义了但是没有被初始化的变量。

设置入口点(entry)

程序执行的第一条指令称为入口点。你可以使用' ENTRY '链接脚本命令来设置入口点。参数是一个符号名:

typescript 复制代码
ENTRY ( symbol )

有几种方法可以设置入口点。链接器将依次尝试以下方法来设置入口点,并在其中一个成功时停止:

  • -e 入口命令选项( 译注 :-e是链接器的参数);
  • 链接脚本中的ENTRY (symbol) 命令 ;
  • 如果符号start定义了,那就是start符号的值;
  • 如果存在.text节,那就是.text节的第一个字节的地址;
  • 地址0

因为在gpl的运行方式中是直接获取text段地址然后跳过去执行,所以这里设置入口点对于gpl是不生效的。uboot 跳过来就会执行uboot_gpl镜像代码段的第一条。

设置输出文件名

' OUTPUT '命令给输出文件命名。使用"OUTPUT ( filename )'就像在命令行中使用' -o filename '一样。如果两者都使用,命令行选项优先。

你可以使用' OUTPUT '命令为输出文件定义一个默认名称,而不是通常默认的' a.out '。

处理目标文件格式的命令

一些链接脚本命令处理目标文件格式。OUTPUT_FORMAT (bfdname)

' OUTPUT_FORMAT '命令给输出文件指定BFD格式的名称。使用' OUTPUT_FORMAT (bfdname)'就像在命令行上使用' -oformat bfdname '一样。如果两者都使用,命令行选项优先。

可以使用带有三个参数的' OUTPUT_FORMAT '来基于' -EB '和' -EL '命令行选项使用不同的格式。这允许链接脚本根据所需的字节序设置输出格式。如果' -EB '和' -EL '都没有使用,那么输出格式将是第一个参数' DEFAULT '。如果使用' -EB ',输出格式将是第二个参数' BIG '。如果使用' -EL ',输出格式将是第三个参数' LITTLE '。例如,MIPS ELF目标的默认链接脚本使用以下命令:

cobol 复制代码
OUTPUT_FORMAT(elf32-bigmips, elf32-bigmips, elf32-littlemips)

这说明输出文件的默认格式是' elf32-bigmips ',但是如果用户使用' -EL '命令行选项,输出文件将以' elf32-littlemips '格式创建。

uboot_gpl 链接脚本的一般写法

SECTIONS{
	. = 0x00;				//位置定位
	.text :					//代码段
	{
		source/main.o
		*(.text)
	}
	.rodata ALIGN(4) : {*(.rodata*)}    	//只读数据段    const 变量
	.data ALIGN(4)   : { *(.data) }  	//数据段        已初始化全局变量
	__bss_start = .;  			//定义bss_start 记录bss段开始位置
	.bss ALIGN(4)  : { *(.bss)  *(COMMON) } //bss段         未初始化全局变量
	__bss_end = .;
}
相关推荐
热爱嵌入式的小许3 小时前
Linux基础项目开发1:量产工具——显示系统
linux·运维·服务器·韦东山量产工具
韩楚风7 小时前
【linux 多进程并发】linux进程状态与生命周期各阶段转换,进程状态查看分析,助力高性能优化
linux·服务器·性能优化·架构·gnu
陈苏同学7 小时前
4. 将pycharm本地项目同步到(Linux)服务器上——深度学习·科研实践·从0到1
linux·服务器·ide·人工智能·python·深度学习·pycharm
Ambition_LAO7 小时前
解决:进入 WSL(Windows Subsystem for Linux)以及将 PyCharm 2024 连接到 WSL
linux·pycharm
Pythonliu77 小时前
茴香豆 + Qwen-7B-Chat-Int8
linux·运维·服务器
你疯了抱抱我7 小时前
【RockyLinux 9.4】安装 NVIDIA 驱动,改变分辨率,避坑版本。(CentOS 系列也能用)
linux·运维·centos
追风赶月、7 小时前
【Linux】进程地址空间(初步了解)
linux
栎栎学编程7 小时前
Linux中环境变量
linux
挥剑决浮云 -8 小时前
Linux 之 安装软件、GCC编译器、Linux 操作系统基础
linux·服务器·c语言·c++·经验分享·笔记
小O_好好学9 小时前
CentOS 7文件系统
linux·运维·centos