u-boot分析(一)

由于u-boot比较庞大,所以我们分开来分析,对于一个大型的项目我们想快速的了解其代码架构和内容,最方便的方法就是分析Makefile,所以我们今天以三星的s3c2440来分析Makefile。我们今天通过对u-boot的分析要得到以下内容:

1.        U-boot的入口

2.        链接地址

l  U-boot配置过程分析

我们在编译u-boot之前首先要进行u-boot的配置,以三星的s3c2440为例我们的配置命令是make smdk2440_config,所以我们在u-boot顶层的Makefile中搜索smdk2440_config我们可以轻松的找到下面代码:

1 smdk2440_config : unconfig
2 @$(MKCONFIG) $(@:_config=) arm s3c24xx smdk2440 samsung s3c2440

从上面代码我们可以确定当我们执行make smdk2440_config的时候其执行了@$(MKCONFIG) $(@:_config=) arm s3c24xx smdk2440 samsung s3c2440在Makefile中我们又可以找到MKCONFIG    := $(SRCTREE)/mkconfig所以上面的命令就可以替换为mkconfig smdk2440 arm s3c24xx smdk2440 samsung s3c2440 也就是说我们执行make smdk2440_config的时候其就是执行上面的命令。

接下来我们打开mkconfig

1.        分析传入的参数,确定开发板的名称,由于我们没有-- 、-a、-n参数所以下面代码可以忽略。

 1 APPEND=no # Default: Create new config file
 2 BOARD_NAME=""# Name to print in make output
 3 SETMMU="no"# use mmu in nand uboot,but do not use in mmc.bin
 4 while[ $# -gt 0 ] ; do
 5 case"$1" in
 6 --) shift ;break;;
 7 -a) shift ; APPEND=yes ;;
 8 -n) shift ; BOARD_NAME="${1%%_config}"; shift ;;
 9 *)break;;
10 esac
11 done
12 ["${BOARD_NAME}"]|| BOARD_NAME="$1"//如果BOARD_NAME已定义后面的代码就不会执行,但是我们这里没有定义,所以执行BOARD_NAME="$1",然而$1 就是smdk2440所以执行完后BOARD_NAME= smdk2440
13 [ $# -lt 4 ] && exit 1//参数的个数小于4退出
14 [ $# -gt 9 ] && exit 1//参数的个数大于9退出
15 echo "Configuring for ${BOARD_NAME} board which boot from $7 $8 $9..."

接下来会打印Configuring for ${BOARD_NAME} board which boot from ...

  1.  1 #
     2 # Create link to architecture specific headers
     3 #
     4 if["$SRCTREE"!="$OBJTREE"]; then
     5 mkdir -p ${OBJTREE}/include
     6 mkdir -p ${OBJTREE}/include2
     7 cd ${OBJTREE}/include2
     8 rm -f asm
     9 ln -s ${SRCTREE}/include/asm-$2 asm
    10 LNPREFIX="../../include2/asm/"
    11 cd ../include
    12 rm -rf asm-$2
    13 rm -f asm
    14 mkdir asm-$2
    15 ln -s asm-$2 asm
    16 else
    17 cd ./include
    18 rm -f asm
    19 ln -s asm-$2 asm
    20 fi

上面的这个if [ "$SRCTREE" != "$OBJTREE" ] 然而我们在顶层的Makefile中可以找到

  1. OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))//如果定义BUILD_DIR则OBJTREE就为BUILD_DIR没定义就为$(CURDIR)
  2. SRCTREE := $(CURDIR)

通过上面两行代码显然我们可以知道OBJTREE和SRCTREE是相等的,所以执行else分支

  1. 1 cd ./include
    2 rm -f asm
    3 ln -s asm-$2 asm#就是ln –s asm-arm asm

1 1 rm -f asm-$2/arch //rm –f asm-arm/arch
2 2 if[-z "$6"-o "$6"="NULL"]; then//第6个参数为空或者为NULL显然不成立执行else分支
3 3 ln -s ${LNPREFIX}arch-$3 asm-$2/arch
4 4 else
5 5 ln -s ${LNPREFIX}arch-$6 asm-$2/arch//因为LNPREFIX未定义所以该命令类似与ln –s arch- s3c2440 asm-arm/arch
6 6 fi

这里我们发现其建立的链接竟然不是连到arch- s3c2440的而是连到arch- s3c24xx的难道我们错了?这个问题下面会解释到。

1 # create link for s3c24xx SoC
2 if["$3"="s3c24xx"]; then
3 rm -f regs.h
4 ln -s $6.h regs.h//建立链接文件ln –s s3c2440.h regs.h
5 rm -f asm-$2/arch
6 ln -s arch-$3 asm-$2/arch//建立链接文件ln –s arch- s3c24xx asm-arm/arch
7 fi

上面的最后一个连接文件,也就是我们刚才为什么看到不正确的链接了,因为其在这里更改了指向。

  1.  1 # create link for s3c64xx SoC
     2 if["$3"="s3c64xx"];then//我们的"$3"=”s3c24xx”的所以不执行
     3 rm -f regs.h
     4 ln -s $6.h regs.h
     5 rm -f asm-$2/arch
     6 ln -s arch-$3 asm-$2/arch
     7 fi
     8 if["$2"="arm"];then
     9 rm -f asm-$2/proc
    10 ln -s ${LNPREFIX}proc-armv asm-$2/proc//建立链接文件ln -s proc-armv asm-arm/proc
    11 fi

  1. # create link for s3c64xx-mp SoC
    if["$3"="s3c64xx-mp"];then//不相等不执行
    rm -f regs.h
    ln -s $6.h regs.h
    rm -f asm-$2/arch
    ln -s arch-$3 asm-$2/arch
    fi
    #
    # Create include file for Make
    #
    echo "ARCH = $2"> config.mk//输出ARCH = arm到config.mk
    echo "CPU = $3">> config.mk//追加CPU = s3c24xx到 config.mk
    echo "BOARD = $4">> config.mk//追加BOARD = smdk2440 到 config.mk
    ["$5"]&&["$5"!="NULL"]&& echo "VENDOR = $5">> config.mk//我们第5个参数为samsung追加VENDOR =samsung 到 config.mk
    ["$6"]&&["$6"!="NULL"]&& echo "SOC = $6">> config.mk//我们第6个参数为s3c2440追加SOC = s3c2440 到 config.mk

  1.  1 #
     2 # Create board specific header file
     3 #
     4 if["$APPEND"="yes"]// Append to existing config file在开始时我们定义APPEND=no所以执行else分支
     5 then
     6 echo >> config.h
     7 else
     8 > config.h // Create new config file创建一个config.h文件
     9 fi
    10 echo "/* Automatically generated - do not edit */">>config.h//追加/*Automatically generated -do not edit */到config.h
    11 case $7 in//我们没有第7个参数所以不执行
    12 SD)
    13 echo "#define FORLINX_BOOT_SD">> config.h
    14 SETMMU="no"
    15 ;;
    16 NAND)
    17 echo "#define FORLINX_BOOT_NAND">> config.h
    18 SETMMU="yes"
    19 ;;
    20 *)
    21 ;;
    22 esac
    23 case $8 in//我们没有第8个参数所以不执行
    24 ram128)
    25 echo "#define FORLINX_BOOT_RAM128">> config.h
    26 >../board/samsung/smdk6410/config.mk # clear file context
    27 echo "ifndef TEXT_BASE">>../board/samsung/smdk6410/config.mk
    28 if[ ${SETMMU}="yes"]
    29 then
    30 echo "TEXT_BASE = 0xC7E00000">>../board/samsung/smdk6410/config.mk
    31 else
    32 echo "TEXT_BASE = 0x57E00000">>../board/samsung/smdk6410/config.mk
    33 fi
    34 echo "endif">>../board/samsung/smdk6410/config.mk
    35 ;;
    36 ram256)
    37 echo "#define FORLINX_BOOT_RAM256">> config.h
    38 >../board/samsung/smdk6410/config.mk # clear file context
    39 echo "ifndef TEXT_BASE">>../board/samsung/smdk6410/config.mk
    40 if[ ${SETMMU}="yes"]
    41 then
    42 echo "TEXT_BASE = 0xCFE00000">>../board/samsung/smdk6410/config.mk
    43 else
    44 echo "TEXT_BASE = 0x5FE00000">>../board/samsung/smdk6410/config.mk
    45 fi
    46 echo "endif">>../board/samsung/smdk6410/config.mk
    47 ;;
    48 *)
    49 ;;
    50 esac
    51 if["$9"="hdmi"];then//我们没有第9个参数所以不执行
    52 echo "#define FORLINX_LCDOUT_HDMI">> config.h
    53 fi
    54 echo "#include <configs/$1.h>">>config.h//追加#include <configs/ smdk2440.h>到 config.h
    55
    56 exit 0

在我们的配置过程中我们主要有一下工作;

1.        创建于开发板相关的头文件的链接

2.        创建include/config.mk文件

3.        创建include/config.h头文件

l  U-boot编译

在我们执行make的时候其将会生成第一个目标也就是all,以all为突破口我们找到all又依赖于$(ALL)而ALL又等于

  1. 1 ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)

而u-boot.srec u-boot.bin又依赖于u-boot

  1. $(obj)u-boot: depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)
    UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e ‘s/.*\(__u_boot_cmd_.*\)/-u\1/p‘|sort|uniq`;cd $(LNDIR)&& $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) --start-group $(__LIBS)--end-group $(PLATFORM_LIBS) -Map u-boot.map -o u-boot

通过展开编译命令(当然有点麻烦)我们可以直接执行make然后找到和这条命令相似的命令,通过得到的命令我们可以顺利的找到其在编译过程中所用到的链接器脚本

  1.  1 OUTPUT_FORMAT("elf32-littlearm","elf32-littlearm","elf32-littlearm")
     2 OUTPUT_ARCH(arm)
     3 ENTRY(_start)//入口地址_start
     4 SECTIONS
     5 {
     6 .=0x00000000;
     7 .= ALIGN(4);
     8 .text ://代码段排布
     9 {
    10 cpu/s3c24xx/start.o (.text)//先是该代码,最先运行
    11 cpu/s3c24xx/s3c2440/cpu_init.o (.text)
    12 *(.text)
    13 }
    14 .= ALIGN(4);
    15 .rodata :{*(.rodata)}
    16 .= ALIGN(4);
    17 .data :{*(.data)}
    18 .= ALIGN(4);
    19 .got :{*(.got)}
    20 .=.;
    21 __u_boot_cmd_start =.;
    22 .u_boot_cmd :{*(.u_boot_cmd)}
    23 __u_boot_cmd_end =.;
    24 .= ALIGN(4);
    25 .mmudata :{*(.mmudata)}
    26 .= ALIGN(4);
    27 __bss_start =.;
    28 .bss :{*(.bss)}
    29 _end =.;
    30 }

在cpu/s3c24xx/start.o我们可以轻松找到其所有代码的入口

  1.  1 .globl _start
     2 _start:
     3 b reset
     4 ldr pc, _undefined_instruction
     5 ldr pc, _software_interrupt
     6 ldr pc, _prefetch_abort
     7 ldr pc, _data_abort
     8 ldr pc, _not_used
     9 ldr pc, _irq
    10 ldr pc, _fiq

至此我们找到了正个程序的入口,但是其的链接地址又在什么地方呢?

我们在顶层的config.mk中找到

  1. 1 LDFLAGS +=-Bstatic-T $(LDSCRIPT)-Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)

其实整个程序的链接地址就在TEXT_BASE通过全局搜索我们在\board\samsung\smdk2440\config.mk 中找到TEXT_BASE = 0x30008000至此我们今天的任务完成。

时间: 2024-10-10 01:37:49

u-boot分析(一)的相关文章

android uboot中的mmc命令

一:mmc的命令如下: 1:对mmc读操作 mmc read addr blk# cnt 2:对mmc写操作 mmc write addr blk# cnt 3:对mmc擦除操作 mmc erase blk# cnt 4:重新搜索mmc设备 mmc rescan 5:列出mmc的分区 mmc part - lists available partition oncurrent mmc device 6:查看当前的设备号,或者设置设备号及分区 mmc dev [dev] [part] - show

uboot中的mmc命令

一:mmc的命令例如以下: 1:对mmc读操作 mmc read addr blk# cnt 2:对mmc写操作 mmc write addr blk# cnt 3:对mmc擦除操作 mmc erase blk# cnt 4:又一次搜索mmc设备 mmc rescan 5:列出mmc的分区 mmc part - lists available partition oncurrent mmc device 6:查看当前的设备号,或者设置设备号及分区 mmc dev [dev] [part] - s

spring boot应用启动原理分析

spring boot quick start 在spring boot里,很吸引人的一个特性是可以直接把应用打包成为一个jar/war,然后这个jar/war是可以直接启动的,不需要另外配置一个Web Server. 如果之前没有使用过spring boot可以通过下面的demo来感受下. 下面以这个工程为例,演示如何启动Spring boot项目: git clone [email protected]:hengyunabc/spring-boot-demo.git mvn spring-b

Spring Boot实战与原理分析

1:Spring Boot概述与课程概要介绍 2:Spring4 快速入门 3:Spring4 扩展分析(一) 4:Spring4 扩展分析(二) 5:Spring Boot 快速入门 6:Spring Boot 配置分析(一) 7:Spring Boot 配置分析(二) 8:Spring Boot 自动配置 9:Spring Boot @Enable*注解的工作原理 10:Spring Boot @EnableAutoConfiguration深入分析 11:Spring Boot 事件监听

Spring Boot 揭秘与实战 源码分析 - 开箱即用,内藏玄机

文章目录 1. 开箱即用,内藏玄机 2. 总结 3. 源代码 Spring Boot提供了很多"开箱即用"的依赖模块,那么,Spring Boot 如何巧妙的做到开箱即用,自动配置的呢? 开箱即用,内藏玄机 Spring Boot提供了很多"开箱即用"的依赖模块,都是以spring-boot-starter-xx作为命名的.例如,之前提到的 spring-boot-starter-redis.spring-boot-starter-data-mongodb.spri

Spring Boot实战与原理分析视频课程

1.Spring Boot概述与课程概要介绍 2.Spring4 快速入门 3.Spring4 扩展分析(一) 4.Spring4 扩展分析(二) 5.Spring Boot 快速入门 6.Spring Boot 配置分析(一) 7.Spring Boot 配置分析(二) 8.Spring Boot 自动配置 9.Spring Boot @Enable*注解的工作原理 10.Spring Boot @EnableAutoConfiguration深入分析 11.Spring Boot 事件监听

spring boot实战(第十五篇)嵌入tomcat源码分析

嵌入tomcat源码分析 在启动spring boot工程时利用@SpringBootApplication注解,该注解启动@EnableAutoConfiguration自动配置,加载META-INF/spring.factories文件 # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.boot.autoconfigure.admin.Spri

Spring Boot 揭秘与实战 源码分析 - 工作原理剖析

文章目录 1. EnableAutoConfiguration 帮助我们做了什么 2. 配置参数类 – FreeMarkerProperties 3. 自动配置类 – FreeMarkerAutoConfiguration4. 扩展阅读 3.1. 核心注解 3.2. 注入 Bean 结合<Spring Boot 揭秘与实战 源码分析 - 开箱即用,内藏玄机>一文,我们再来深入的理解 Spring Boot 的工作原理. 在<Spring Boot 揭秘与实战 源码分析 - 开箱即用,内藏

理解boot.img与逆向分析Android/linux内核

一些尝试和理解. 1>提取boot.img: 其中,msm代表是高通的芯片,msm_sdcc.1是外接的SD卡挂载的目录,by-name指的是这个sd卡分区的名称.下面几行代表每个分区存储的东西. 记得提前su,dd if=/dev/block/mmcblk0p8 of=/data/local/tmp/boot.img.将boot.img dump出来 adb root获得root权限,将boot.img 移到pc上. 2>boot.img格式分析 如system/core/mkbootimg

nova boot代码流程分析(三):nova与neutron的交互(2)

继续<nova boot代码流程分析(三):nova与neutron的交互(1)>的分析. #/nova/virt/libvirt/driver.py:LibvirtDriver # NOTE(ilyaalekseyev): Implementation like in multinics # for xenapi(tr3buchet) def spawn(self, context, instance, image_meta, injected_files, admin_password,