移植uboot第二步:分析uboot

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可以生成位置无关的可执行程序。

猜你喜欢

转载自blog.csdn.net/ltc844139730/article/details/52171656