移植uboot第二步:分析uboot

写在前面:

我的博客已迁移至自建服务器:博客传送门,CSDN博客暂时停止,如有机器学习方面的兴趣,欢迎来看一看。

此外目前我在gitHub上准备一些李航的《统计学习方法》的实现算法,目标将书内算法全部手打实现,欢迎参观并打星。GitHib传送门

正文

1.在make的过程中,最后会显示链接文件,如下

UNDEF_SYM=`arm-linux-objdump -x board/samsung/smdk2410/libsmdk2410.o api/libapi.o arch/arm/cpu/arm920t/libarm920t.o arch/arm/cpu/arm920t/s3c24x0/libs3c24x0.o arch/arm/lib/libarm.o common/libcommon.o disk/libdisk.o drivers/bios_emulator/libatibiosemu.o drivers/block/libblock.o drivers/dma/libdma.o drivers/fpga/libfpga.o drivers/gpio/libgpio.o drivers/hwmon/libhwmon.o drivers/i2c/libi2c.o drivers/input/libinput.o drivers/misc/libmisc.o drivers/mmc/libmmc.o drivers/mtd/libmtd.o drivers/mtd/nand/libnand.o drivers/mtd/onenand/libonenand.o drivers/mtd/spi/libspi_flash.o drivers/mtd/ubi/libubi.o drivers/net/libnet.o drivers/net/phy/libphy.o drivers/pci/libpci.o drivers/pcmcia/libpcmcia.o drivers/power/libpower.o drivers/rtc/librtc.o drivers/serial/libserial.o drivers/spi/libspi.o drivers/twserial/libtws.o drivers/usb/eth/libusb_eth.o drivers/usb/gadget/libusb_gadget.o drivers/usb/host/libusb_host.o drivers/usb/musb/libusb_musb.o drivers/usb/phy/libusb_phy.o drivers/usb/ulpi/libusb_ulpi.o drivers/video/libvideo.o drivers/watchdog/libwatchdog.o fs/cramfs/libcramfs.o fs/ext2/libext2fs.o fs/fat/libfat.o fs/fdos/libfdos.o fs/jffs2/libjffs2.o fs/reiserfs/libreiserfs.o fs/ubifs/libubifs.o fs/yaffs2/libyaffs2.o lib/libfdt/libfdt.o lib/libgeneric.o lib/lzma/liblzma.o lib/lzo/liblzo.o lib/zlib/libz.o net/libnet.o post/libpost.o | sed  -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`; cd /work/system/u-boot-2012.04.01 && arm-linux-ld  -pie -T u-boot.lds -Bstatic -Ttext 0x0 $UNDEF_SYM arch/arm/cpu/arm920t/start.o --start-group api/libapi.o arch/arm/cpu/arm920t/libarm920t.o arch/arm/cpu/arm920t/s3c24x0/libs3c24x0.o arch/arm/lib/libarm.o common/libcommon.o disk/libdisk.o drivers/bios_emulator/libatibiosemu.o drivers/block/libblock.o drivers/dma/libdma.o drivers/fpga/libfpga.o drivers/gpio/libgpio.o drivers/hwmon/libhwmon.o drivers/i2c/libi2c.o drivers/input/libinput.o drivers/misc/libmisc.o drivers/mmc/libmmc.o drivers/mtd/libmtd.o drivers/mtd/nand/libnand.o drivers/mtd/onenand/libonenand.o drivers/mtd/spi/libspi_flash.o drivers/mtd/ubi/libubi.o drivers/net/libnet.o drivers/net/phy/libphy.o drivers/pci/libpci.o drivers/pcmcia/libpcmcia.o drivers/power/libpower.o drivers/rtc/librtc.o drivers/serial/libserial.o drivers/spi/libspi.o drivers/twserial/libtws.o drivers/usb/eth/libusb_eth.o drivers/usb/gadget/libusb_gadget.o drivers/usb/host/libusb_host.o drivers/usb/musb/libusb_musb.o drivers/usb/phy/libusb_phy.o drivers/usb/ulpi/libusb_ulpi.o drivers/video/libvideo.o drivers/watchdog/libwatchdog.o fs/cramfs/libcramfs.o fs/ext2/libext2fs.o fs/fat/libfat.o fs/fdos/libfdos.o fs/jffs2/libjffs2.o fs/reiserfs/libreiserfs.o fs/ubifs/libubifs.o fs/yaffs2/libyaffs2.o lib/libfdt/libfdt.o lib/libgeneric.o lib/lzma/liblzma.o lib/lzo/liblzo.o lib/zlib/libz.o net/libnet.o post/libpost.o board/samsung/smdk2410/libsmdk2410.o --end-group /work/system/u-boot-2012.04.01/arch/arm/lib/eabi_compat.o  -L /usr/local/arm/4.3.2/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.2/armv4t -lgcc -Map u-boot.map -o u-boot

其中 arm-linux-ld -pie -T u-boot.lds -Bstatic -Ttext 0x0 $UNDEF_SYM arch/arm/cpu/arm920t/start.o --start-group api/libapi.o arch/arm/cpu/arm920t/libarm920t.o 这句话就是链接,打开start.S,看看里面是什么内容。

2.分析start.S
1.进入管理模式,代码开始执行,

start_code:
	/*
	 * set the cpu to SVC32 mode
	 */
	mrs	r0, cpsr
	bic	r0, r0, #0x1f
	orr	r0, r0, #0xd3
	msr	cpsr, r0

2.关闭看门狗
ldr	r0, =pWTCON
	mov	r1, #0x0
	str	r1, [r0]

3.屏蔽中断
/*
	 * mask all IRQs by setting all bits in the INTMR - default
	 */
	mov	r1, #0xffffffff
	ldr	r0, =INTMSK
	str	r1, [r0]

4.设置分频系数
/* FCLK:HCLK:PCLK = 1:2:4 */
	/* default FCLK is 120 MHz ! */
	ldr	r0, =CLKDIVN
	mov	r1, #3
	str	r1, [r0]

4.板子初始化,这里开始使用C函数,所以要初始化栈
call_board_init_f:
	ldr	sp, =(CONFIG_SYS_INIT_SP_ADDR)
	bic	sp, sp, #7 /* 8-byte alignment for ABI compliance */
	ldr	r0,=0x00000000
	bl	board_init_f

5.进入call_board_init_f函数
这里初始化了一个指针,指向了栈的同一位置,他们并不冲突,栈是向下 增长的,指针是向上的。

gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);

可以看到存了一些数据进入,关于bss段以及一些其他信息的,还有很多gd的配置,没有贴出来,占了挺大一段的

gd->mon_len = _bss_end_ofs;

这里面有这句话,init_fnc_ptr 是一个指针,init_sequence是一个数组,里面有很多函数,这个for就是去循环执行这些函数

for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
		if ((*init_fnc_ptr)() != 0) {
			hang ();
		}
	}

里面都是条件编译,我把没宏定义的代码段都去掉了,留下的函数是执行函数,看起来比较方便

init_fnc_t *init_sequence[] = {

#if defined(CONFIG_BOARD_EARLY_INIT_F)
	board_early_init_f,
#endif
	timer_init,		/* initialize timer */
#endif
	env_init,		/* initialize environment */
	init_baudrate,		/* initialze baudrate settings */
	serial_init,		/* serial communications setup */
	console_init_f,		/* stage 1 init of console */
	display_banner,		/* say that we are here */
#if defined(CONFIG_DISPLAY_CPUINFO)
	print_cpuinfo,		/* display cpu info (and speed) */
#endif
	dram_init,		/* configure available RAM banks */
	NULL,
};

5.1 board_early_init_f,板子早期初始化函数
设置了分频系数,有点奇怪汇编里面已经设置过了,我要去查一查两个哪个是对的

writel(0xFFFFFF, &clk_power->locktime);

	/* configure MPLL */
	writel((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV,
	       &clk_power->mpllcon);

	/* some delay between MPLL and UPLL */
	pll_delay(4000);

	/* configure UPLL */
	writel((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV,
	       &clk_power->upllcon);

GPIO端口的初始化
/* set up the I/O ports */
	writel(0x007FFFFF, &gpio->gpacon);
	writel(0x00044555, &gpio->gpbcon);
	writel(0x000007FF, &gpio->gpbup);
	writel(0xAAAAAAAA, &gpio->gpccon);
	writel(0x0000FFFF, &gpio->gpcup);
	writel(0xAAAAAAAA, &gpio->gpdcon);
	writel(0x0000FFFF, &gpio->gpdup);
	writel(0xAAAAAAAA, &gpio->gpecon);
	writel(0x0000FFFF, &gpio->gpeup);
	writel(0x000055AA, &gpio->gpfcon);
	writel(0x000000FF, &gpio->gpfup);
	writel(0xFF95FFBA, &gpio->gpgcon);
	writel(0x0000FFFF, &gpio->gpgup);
	writel(0x002AFAAA, &gpio->gphcon);
	writel(0x000007FF, &gpio->gphup);

5.2 在int timer_init(void)里面,有一个get_PCLK()函数被调用,再往里走get_HCLK(),再往里走

ulong get_HCLK(void)
{
	struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
#ifdef CONFIG_S3C2440
	switch (readl(&clk_power->clkdivn) & 0x6) {
	default:
	case 0:
		return get_FCLK();
	case 2:
		return get_FCLK() / 2;
	case 4:
		return (readl(&clk_power->camdivn) & (1 << 9)) ?
			get_FCLK() / 8 : get_FCLK() / 4;
	case 6:
		return (readl(&clk_power->camdivn) & (1 << 8)) ?
			get_FCLK() / 6 : get_FCLK() / 3;
	}

可以看出里面是有关于2440的宏定义的,当前并没有被定义,所以之后要把这段代码宏定义了,才能执行。
到这里已经有点懵逼了,uboot的代码绕圈程度有点大了。要改的地方感觉挺多的,移植的难度应该会很大。

6.在board_init_f函数的最后面relocate_code(addr_sp, id, addr);重定位代码。
在反汇编文件中一开始的代码位置就是0,让人感觉不需要重定位了。

u-boot:     file format elf32-littlearm

Disassembly of section .text:

00000000 <__image_copy_start>:
       0:	ea000013 	b	54 <start_code>
       4:	e59ff014 	ldr	pc, [pc, #20]	; 20 <_undefined_instruction>
       8:	e59ff014 	ldr	pc, [pc, #20]	; 24 <_software_interrupt>
       c:	e59ff014 	ldr	pc, [pc, #20]	; 28 <_prefetch_abort>
      10:	e59ff014 	ldr	pc, [pc, #20]	; 2c <_data_abort>
      14:	e59ff014 	ldr	pc, [pc, #20]	; 30 <_not_used>
      18:	e59ff014 	ldr	pc, [pc, #20]	; 34 <_irq>
      1c:	e59ff014 	ldr	pc, [pc, #20]	; 38 <_fiq>

00000020 <_undefined_instruction>:
      20:	000001e0 	.word	0x000001e0

实际上是链接的时候可以看到 arm-linux-ld -pie -T u-boot.lds -Bstatic -Ttext ,输入命令arm-linux-ld --help | grep pie,搜索pie命令,回复-pie, --pic-executable Create a position independent executable,也就是说链接的时候加上pie可以生成位置无关的可执行程序。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值