水浒传鲁智深故事:7.3 通用的引导装入程序:Das U-Boot

来源:百度文库 编辑:中财网 时间:2024/03/28 23:59:59

    7.3 通用的引导装入程序:Das U-Boot

    有许多开源或商业的引导装入程序可用,而且,很多厂商针对某平台设计的程序现在也在广为应用,其中大多数都具有通用的特性。例如,它们都具备载入和执行其他程序的能力,特别是操作系统。大多数通过串口与用户进行交互。支持不同的网络子系统(例如以太网)不是非常普遍,但却是一个非常有用的特性。

    许多引导装入程序都特定于某一种体系结构。对于一些规模较大的开发组织来说,引导装入程序能够支持非常广泛的体系结构和处理器,是非常重要的。对于个体开发,支持多种体系结构的多个处理器也并不少见。为多种交叉平台开发单一的引导装入程序会降低开发成本。

    本节将研究在嵌入式Linux社区中已经非常流行的引导装入程序。这个引导装入程序的官方命名是Das U-Boot,由Wolfgang Denk维护,在SourceForge上的主页是http://u-boot.sourceforge.net/。U-Boot支持多种体系结构,许多嵌入式开发者和厂商都在项目中采用U-Boot,并从中获益。

    7.3.1 执行上下文

    要让引导装入程序能够适用于多种处理器和体系结构平台,也需要一些配置手段。就像Linux内核本身那样,引导装入程序的配置在编译时完成。这种方法特别减少了引导装入程序的复杂程度,这也是它的一个重要特性。

    在U-Boot中,板级相关的配置由目标平台相关的个别头文件和源码树中的一些软连接指定。这些软连接会根据不同的目标板、体系结构和处理器选择正确的子目录。为支持平台配置U-Boot,可以使用下面的命令:

    1. $ make _config 

    此处platform是U-Boot所支持的众多平台之一。这些平台配置目标在U-Boot顶层目录中的makefile文件中列出。例如,为Spectrum Digital OSK开发板配置U-Boot,可以使用下面的命令。该平台使用了TI 公司的OMAP 5912处理器:

    1. $ make omap5912osk_config 

    这样配置以后,U-Boot源码树将使用恰当的软连接进行选择:ARM作为目标体系结构,ARM926核,5912 OSK作为目标平台。

    为该平台配置U-Boot的下一个步骤是编辑与平台相关的配置文件,这个文件在../include/ configs子目录中,文件名是omap5912osk.h。随U-Boot发行版提供的README文件中描述了配置的细节内容。README文件也是获得此类信息的最佳资源。

    使用配置变量完成U-Boot的配置,这些配置在板级相关的头文件中定义。其中有两种形式的配置变量:使用CONFIG_XXX形式的宏选择配置选项;使用CFG_XXX形式的宏选择配置选项。一般说来,配置选项(CONFIG_XXX)是用户可配置的,它体现了U-Boot的灵活、可选的特征。配置选项(CFG_XXX)通常和硬件相关,需要我们理解处理器和硬件平台的内部细节。与板级相关的U-Boot配置由专门描述具体平台的头文件决定,这个文件包括了针对平台底层的配置选项和设置。这些板级相关的配置头文件都保存在U-Boot源码树的一个子目录中,具体为.../include/configs。

    在板级相关的配置文件中添加定义,可以选择许多特性和模式。代码清单7-4列出了一个配置文件的部分内容,该文件取自一个假想的基于PPC 405GP处理器的开发板。

    代码清单7-4 U-Boot 板级相关配置头文件部分内容

    1. #define CONFIG_405GP        /* Processor definition */  
    2. #define CONFIG_4XX          /* Sub-arch specification, 4xx family */  
    3.  
    4. #define CONFIG_SYS_CLK_FREQ   33333333 /* PLL Frequency  */  
    5. #define CONFIG_BAUDRATE       9600  
    6. #define CONFIG_PCI          /* Enable support for PCI */  
    7. ...  
    8. #define CONFIG_COMMANDS      (CONFIG_CMD_DFL | CFG_CMD_DHCP)  
    9. ...  
    10. #define CFG_BASE_BAUD        691200  
    11.  
    12. /* The following table includes the supported baudrates */  
    13. #define CFG_BAUDRATE_TABLE  \  
    14.     {1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400}  
    15.  
    16. #define CFG_LOAD_ADDR        0x100000    /* default load address */  
    17. ...  
    18. /* Memory Bank 0 (Flash Bank 0) initialization */  
    19. #define CFG_EBC_PB0AP         0x9B015480  
    20. #define CFG_EBC_PB0CR         0xFFF18000  
    21.  
    22. #define CFG_EBC_PB1AP         0x02815480  
    23. #define CFG_EBC_PB1CR         0xF0018000  
    24. ... 

    代码清单7-4给出了U-Boot自身如何配置给定开发板的一种思路,一个实际的板级相关的配置文件可能包含数百行之多。在本例中,你可以看到CPU的定义、CPU系列(4xx)、PLL时钟频率、串口波特率和PCI支持的定义,还包括了配置变量(CONFIG_XXX)和配置设置(CFG_XXX)的实例。最后几行是真实的处理器寄存器的值,初始外部总线控制器需要这些值。你可以发现,这些值只有深入了解开发板和处理器以后才能获得。

    通过使用这种机制,可以配置U-Boot的很多方面,包括编译哪些功能(支持DHCP、内存测试、调试等)。这种机制可以用来告知U-Boot,开发板上使用了哪种内存,以及内存大小和内存映射地址。对此感兴趣的读者可以直接阅读U-Boot源代码,特别是非常全面的README文件。


      7.3.2 U-Boot命令集

      U-Boot支持多达60个标准的命令集,使用CFG_*宏可以支持超过150个独特的命令。在U-Boot中,通过使用配置设置(CFG_*)宏可以启用命令集。参考附录A就可以查询最近的U-Boot命令的完整列表。这里给出几个命令,通过它们你就可以了解U-Boot的一些功能。

      代码清单7-4中的下面一行定义了U-Boot配置中可用的命令,它在板级相关的头文件中给出:

      1. #define CONFIG_COMMANDS        (CONFIG_CMD_DFL | CFG_CMD_DHCP) 

      在你自己的板级相关的配置头文件中,如果不想一个一个地输入CFG_*宏,可以从U-Boot源代码中预定义的默认命令集开始。CONFIG_CMD_DFL宏定义了这个默认的命令集,该宏指定了默认的U-Boot命令集列表,例如tftpboot(从tftp服务器启动映像)命令、bootm(从内存启动一个映像)命令、md(显示内存)之类的内存工具,等等。为了启用你自定义的命令组合,需要用默认的方式开头,并根据需要进行添加和删除。代码清单7-4的示例中,增加了DHCP命令。以类似的方式,你可以去除命令:

      1. #define CONFIG_COMMANDS    (CONFIG_CMD_DFL & ~CFG_CMD_NFS) 
      请查看.../include/configs/中板级相关的头文件获得更多示例。

      7.3.3 网络操作

      许多引导装入程序都包括了对以太网接口的支持。在开发环境中,这会极大地节省时间。通过串口载入一个中等规模的内核映像可能需要数分钟之久,而使用10Mbit/s的以太网连接仅需要几秒钟。此外,使用功能较弱的串口终端的串口连接更容易产生错误。

      引导装入程序中一些更重要的特征是包括对BOOTP、DHCP和TFTP协议的支持。这些协议不常见,BOOTP(启动协议)和DHCP(动态主机控制协议)是允许目标设备通过以太网端口从中央服务器获取IP地址和其他网络相关配置信息的一种协议。TFTP(轻量级文件传输协议)允许目标设备从TFTP服务器下载文件(例如Linux内核映像)。请参考本章结尾列出的这些协议规范。完成这些服务的服务器将在第12章加以说明。

      图7-1阐述了目标设备和BOOTP服务器之间的信息流。客户(在本案例中是U-Boot)开始发送一个广播包搜索BOOTP服务器。这个服务器返回一个数据包作为响应,该数据包中包含了客户端的IP地址和其他信息。最有用的数据是下载的内核映像的文件名。

       (点击查看大图)图7-1 BOOTP客户/服务器握手

      在开发过程中,BOOTP服务器不再作为单一的服务器存在。在你喜欢的Linux发行版中包括了DHCP服务器,也同样包括了BOOTP协议。

      DHCP协议建立在BOOTP之上,它能为目标平台提供相当多的配置信息。在开发过程中,信息交换通常被目标/引导装入程序(DHCP客户端)限制。代码清单7-5列出了一个DHCP服务器的配置,该配置可以识别一个目标设备。该片段取自Fedora Core 2中DHCP服务的配置文件。

      代码清单7-5 DHCP目标规范

      1. host coyote {  
      2.       hardware ethernet 00:0e:0c:00:82:f8;  
      3.       netmask 255.255.255.0;  
      4.       fixed-address 192.168.1.21;  
      5.       server-name 192.168.1.9;  
      6.       filename "coyote-zImage";  
      7.       option root-path "/home/chris/sandbox/coyote-target";  
      8. }  
      9. ... 

      当DHCP服务器收到来自与硬件以太网地址(代码清单7-5中给出)相匹配的设备的数据包时,它将把参数按照目标规范的格式发送给目标设备来作出响应。表7-1说明了目标规范中的字段。

      表7-1 DHCP目标参数

      DHCP目标参数

      用途

      注释

      host

      主机名

      DHCP 配置文件的符号标签

      hardware ethernet

      以太网硬件地址

      目标机的以太网接口

      使用的底层以太网硬件地址

      fixed-address

      目标机IP地址

      目标机使用的IP地址

      netmask

      目标机子网掩码

      目标机使用的IP子网掩码

      server-name

      TFTP 服务器 IP 地址

      IP地址,目标机以此地址直

      接请求文件传输、根文件系统等

      filename

      TFTP下载的文件名

      引导装入程序使用该文件名

      启动第2个映像(一般来

      说是Linux内核)


      当目标板上的引导装入程序完成BOOTP或DHCP交换以后,前面说过的参数将用于更多的配置。例如,引导装入程序会使用目标板的IP地址和它的以太网端口进行绑定,然后使用server-name列指定的目的IP地址请求filename列中的文件,在大多数情况下,这个文件通常是Linux内核映像。虽然这是大多数情况,但也可以想象它可能会是厂商测试和诊断固件的程序。

      请注意,DHCP协议支持的参数要远远多于表7-1列出的,表中给出的只是你在嵌入式系统中最有可能遇到的一些参数。要获得完整的信息请参考本章结尾给出的DHCP规范参考资料。
       

      7.3.4 存储子系统

      很多引导装入程序具有支持从各种存储设备而不仅仅是常用的闪存中启动映像的能力。支持多种存储类型设备的难度在于软硬件之间的复杂联系。例如,要访问硬盘上的数据,引导装入程序必须有IDE控制器接口的驱动程序,还要了解分区方案和文件系统类型。这并非没有价值,它是成熟操作系统中的一项任务。

      虽然有些复杂,但从这类设备中载入映像还是有多种方法可寻的。最简单的方法是只支持硬件。使用这种方法,不需要了解文件系统的知识,引导装入程序只是从设备的绝对扇区里载入数据。这种方法适用在与IDE兼容设备(例如CF卡)的未格式化的分区中,从0扇区开始载入找到的数据,这些数据没有任何的结构组织。对于载入内核映像或者其他二进制映像文件,这是一种理想的配置。设备上的其他分区可以被格式化为指定的文件系统。内核启动以后,设备驱动程序用来访问其他分区。

      U-Boot可以从指定的分区或带有文件系统结构的分区载入映像,当然,开发板必须支持硬件设备(IDE子系统),同时U-Boot也必须按此进行配置。在板级相关的配置文件中增加CFG_CMD_IDE后,就启用了对IDE接口的支持,且增加CFG_CMD_BOOTD将启用从原始分区启动的功能。如果要将U-Boot移植到自己的开发板,你就必须修改U-Boot代码以满足特殊的硬件。

      7.3.5 从磁盘启动:U-Boot

      正如前一节所述,U-Boot支持几种从磁盘子系统启动内核映像的方法。下面这条简单的命令说明了其中支持的一种方法:

      1. => diskboot 0x400000 0:0 

      要了解上面的语法,必须首先理解U-Boot是如何计数磁盘设备的。本例中的0:0说明了设备和分区。在这个简单的实例中,U-Boot执行一个原始的二进制程序,这个程序是从所找到的第1块IDE设备(IDE设备0)的第1个分区中载入的映像,该映像会被载入到物理地址0x400000处。

      内核映像被载入到内存后,U-Boot使用bootm(从内存启动)命令启动内核:

      1. => bootm 0x400000