uboot中的 standalone hello_world.bin

arm64平台,2022uboot

编译:

        在 menu "General setup"下勾选选config EXAMPLES:    bool "Compile API examples"。编译完成后会在examples/standalone目录下生成hello_world.bin。将这个bin放在可执行地址,使用go命令跳转过去执行。当无.bss段时,这个bin可以在任意地址执行。

   

=> go 80000000
    ## Starting application at 0x80000000 ...
    Example expects ABI version 9
    Actual U-Boot ABI version 9
    Hello World
    argc = 1
    argv[0] = "80000000"
    argv[1] = "<NULL>"
    Hit any key to exit ...

代码原理:

 hello_world.c中

int hello_world(int argc, char *const argv[])
{
	int i;

	/* Print the ABI version */
	app_startup(argv);
	printf ("Example expects ABI version %d\n", XF_VERSION);
	printf ("Actual U-Boot ABI version %d\n", (int)get_version());

	printf ("Hello World\n");

	printf ("argc = %d\n", argc);

	for (i=0; i<=argc; ++i) {
		printf ("argv[%d] = \"%s\"\n",
			i,
			argv[i] ? argv[i] : "<NULL>");
	}

	printf ("Hit any key to exit ... ");
	while (!tstc())
		;
	/* consume input */
	(void) getc();

	printf ("\n\n");
	return (0);
}

        其中 app_startup(argv)功能为清零BSS段。

        通过反汇编可以知道,其他printf,tstc,getc等函数并不是真正在helloworld.bin中实现了;都是一层封装函数,先获取gd中的固定偏移地址,再从此偏移地址的某个偏移获取对应函数的地址,并跳转。对照代码可以看到使用的是gd里保存的jt结构体。

struct jt_funcs *jt; 初始化在common\exports.c中:

#define EXPORT_FUNC(f, a, x, ...)  gd->jt->x = f;

void jumptable_init(void)
{
	gd->jt = malloc(sizeof(struct jt_funcs));
#include <_exports.h>
}

结构体定义在include\exports.h中:

struct jt_funcs {
#define EXPORT_FUNC(impl, res, func, ...) res(*func)(__VA_ARGS__);
#include <_exports.h>
#undef EXPORT_FUNC
};

        可以看到,正在这两个文件中,EXPORT_FUNC宏定义不同,因此<_exports.h>头文件展开之后的作用也不同;在include\exports.h中是完成jt_funcs结构体,将一系列函数指针加入到为该结构体成员中。在common\exports.c则是对结构体成员进行赋值。

        在examples\stanalone\stubs.c中,EXPORT_FUNC宏定义不同又有不同。展开之后就是从gd->jt中获取函数地址并跳转的流程。在这个文件中的作用是将需要用的函数制作出同名的封装函数。

/*
 * x18 holds the pointer to the global_data, x9 is a call-clobbered
 * register
 */
#define EXPORT_FUNC(f, a, x, ...) \
	asm volatile (			\
"	.globl " #x "\n"		\
#x ":\n"				\
"	ldr	x9, [x18, %0]\n"		\
"	ldr	x9, [x9, %1]\n"		\
"	br	x9\n"		\
	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "x9");
void __attribute__((unused)) dummy(void)
{
#include <_exports.h>
}

 

        通过以上代码的分析可以得出,想在hello_world.c中调用其他函数,只需要在include\_exports.h中添加对应函数的EXPORT_FUNC宏声明,再在include\exports.h中添加函数声明。

 

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值