2013年3月19日 星期二

[嵌入式系統] Ch6-2 Android BSP+開機流程 + 設定檔編輯及詳解


本章將依序介紹
1.Android BSP包 資料夾的意義
2.開機流程及說明

3.[嵌入式系統]Android 原廠-Bootloader build

4.[嵌入式系統]Android 原廠-Kernel        build

5.[嵌入式系統]Android 原廠-Image         build
===============================================
1.Android BSP包 資料夾的意義
android最上層目錄結構如下:
|-- Makefile        (全域的Makefile)
|-- bionic          (Bionic含意為仿生,這裡面主要放一些基礎的libraries的source code)
|-- bootloader    (開機時bootload環境build的source code)
|-- build           (build目錄中的內容不是目標所用的code,而是編譯和配置所需要的script及tools)
|-- dalvik          (Android虛擬機器)
|-- development     (程式開發所需要的樣板和tools)
|-- external        (目標機器使用的一些libraries)
|-- frameworks      (應用程式的架構層)
|-- hardware        (與硬體相關的庫)
|-- kernel          (Linux2.6的Source code)
|-- packages        (Android的各種應用程式)
|-- prebuilt        (Android在各種平台下編譯的預置script)
|-- recovery        (與目標的恢復功能相關)
`-- system          (Android的底層的一些libraries)


2.開機流程及說明
開機順序
Env > bootloader > kernel

env檔主要為開機設定檔 定義bootloader 及 kernel的所在(記憶體位置)及版本
編輯主要需要16進制的編輯軟體
在此我是使用windows 去作編輯
因為是編輯16進制 可以找關鍵字hex editor
使用HxD : http://mh-nexus.de/en/hxd/
(Linux's GUI的hex editor 首推 bless 套件package名稱就叫做bless 可以透過apt-get安裝.)
找到最新版的之後安裝並開啟 並將欲編輯的文件直接拉近去作編輯

編輯完之後補完128k-5的位置
先存檔
再用CRC32檢查工具 將文件的CRC32碼逆向編入文件中00~03的位置
04則填入00或01使文件變成128k長度
行號會補0到1fff0 另存成bin檔 即可作燒寫入的動作
機器有此Env檔 就會按照設定去讀入對應的bootloader(U-boot)及kernel
以目前經驗來說Env檔會直接燒製在機器中,是由工廠用治具來燒製進去


第二步會去載入bootloader (U-boot):
Buildloader在Linux中主要用來決定系統的設定(包含硬體Memory的決定)(舉例來說你的機器是512MB但是bootloader是用1GB就會沒辦法開機,甚至在kernel載入就會有問題:但1G硬體載512MB可以正常開機),支援哪些指令(busy box 及 燒錄指令等)

第三步會依據env去載入kernel:
kernel主要build出取決於硬體有沒有打開通道的依據來讓上層軟體溝通,kernel在我觀念我認為他是framework或HAL層,在硬體跟軟體的中間。

3.[嵌入式系統]Android 原廠-Bootloader build



4.[嵌入式系統]Android 原廠-Kernel        build

在android中要build kernel,若是硬體要打開的話,建議由android/kernel 進去,並下make menuconfig(由各層Kconfig檔组成)進去編輯(【】,【*】,【M】)(或用vim去編輯系統產生的.config文件。在裡面y代表打開,m代表模組化(模組化是為了省空間,但每次要使用需要用mknod來掛載),那我們傾向用y來打開硬體功能。

接下來也可選擇進到底下每一層 觀看Makefile或Kconfig檔(Kconfig的用途為Make選單的建立此外,Kconfig文件跟這些設定結果並沒有直接的關係,只是決定了make menuconfig的選單的選項)來設定:
(注意:由於是樹狀結構目錄,若最底層變動或新增Makefile,上一層也必須新增,否則在build kernel時會發生錯誤或無效)

Ref:
http://blog.csdn.net/flydream0/article/details/7079381:

1 Kconfig和Makefile

毫不夸张地说,Kconfig和Makefile是我们浏览内核代码时最为依仗的两个文件。基本上,Linux 内核中每一个目录下边都会有一个Kconfig文件和一个Makefile文件。Kconfig和Makefile就好似一个城市的地图,地图引导我们去 认识一个城市,而Kconfig和Makefile则可以让我们了解一个内核目录下面的结构。在希望研究内核的某个子系统、某个驱动或其他某个部分时,都 有必要首先仔细阅读一下相关目录下的Kconfig和Makefile文件。
分布到各目录的Kconfig构成了一个分布式的内核配置数据库,每个Kconfig分别描述了所属目录源文档相关的内核配置菜单。在内核配置make menuconfig时,从Kconfig中读出菜单,用户选择后保存到.config的内核配置文档中。 在内核编译时,主Makefile调用这个.config,就知道了用户的选择。
假如想使这个驱动被编译,则要修改Makefile文件,因此,需要添加新的驱动时,需要修改的文件有两个:Kconfig,Makefile.

2 菜单组织结构

一般一个Kconfig文件表示的就是一个菜单,一个菜单由多个菜单项组成,其格式如下:
[html] view plaincopy
  1. menu 菜单名  
  2.   
  3. 菜单项或菜单链接1  
  4. 菜单项或菜单链接2  
  5. ...  
  6. 菜单项或菜单链接n  
  7.   
  8. endmenu  
其中菜单项就是指菜单的子菜单,所谓菜单链接就是指链接到另一个Kconfig文件,如此一下,菜单就可以实现随意嵌套了.
例如:
[html] view plaincopy
  1. # drivers/Kconfig  
  2. menu "Device Drivers"  
  3. source "drivers/base/Kconfig"  
  4. source "drivers/connector/Kconfig"  
  5. source "drivers/mtd/Kconfig"  
  6. source "drivers/of/Kconfig"  
  7. source "drivers/parport/Kconfig"  
  8. source "drivers/pnp/Kconfig"  
  9. source "drivers/block/Kconfig"  
  10. source "drivers/hello/Kconfig"  
  11. config test  
  12.   bool "提示字符串"  
  13.   default y  
  14.   ...  
  15. endmenu   

2.1 菜单项

语法:
[html] view plaincopy
  1. config <symbol>  
  2. <config options>  
为一符号,就好像代码中的局部变量x一样,可用于后边的表达式中.
例如:
[html] view plaincopy
  1. config UEVENT_HELPER_PATH  
  2.        string "path to uevent helper"  
  3.        depends on HOTPLUG  
  4.        default "/sbin/hotplug"  
  5.        help  
  6.       Path to uevent helper program forked by the kernel for  
  7.       every uevent.  
上面菜单项的属性string表示菜单的类型,每一个菜单项必须有一个类型.
注:每个config菜单项都会产生一个配置选项CONFIG_XXX, XXX即为. 如上,则会产生一个配置项:CONFIG_UEVENT_HELPER_PATH,此配置项的值记录在内核根目录下的隐藏文件.config内, 例:~/WORKING_DIRECTORY/kernel/goldfish/.config文件内.

2.2 菜单链接

菜单链接的格式如下:
[html] view plaincopy
  1. source "路径"  
如:
[html] view plaincopy
  1. source "drivers/pnp/Kconfig"  

2.3 菜单属性

2.3.1 类型

类型可以是:bool、tristate、string、hex和int。
bool类型的只能选中或不选中,选中为y,不选中为n.
tristate类型的菜单项为值可为三种值,多了编译成内核模块的选项。其值可为y,n,m.
string类型表示需要用户输入一串字符串。
hex类型则需要用户输入一个16进制数。
int类型表示用户输入一个整型.
总结:
菜单类型属性就好比一个控件,bool相当于单选框,trstate相当于有三种状态的复选框,string相当于供用户输入字符串的文本编辑框,hex相当于供用户输入16进制数的文本编辑框,而int就相当于供用户输入整型数的文本编辑框。
类型关键字后边可跟随提示字符,也可以不跟随,取决于情况。如:
[html] view plaincopy
  1. string "path to uevent helper"  
[html] view plaincopy
  1. bool "Prevent firmware from being built"  

注:每一个菜单项必须有类型属性。

2.3.2 默认值

默认值属性default一般在类型属性后边,如:
[html] view plaincopy
  1. config UEVENT_HELPER_PATH  
  2.     string "path to uevent helper"  
  3.     default "/sbin/hotplug"  
表示当前菜单项若用户没有选择或输入任何值时,所取的默认值.上述所示为当前的默认值为"/sbin/totplug".

2.3.3 依赖

依赖可以是"depends on"或"requires".
语法:
[html] view plaincopy
  1. depends on/requires <expr>  

为表达式,可为之前定义的菜单项名.
如:
[html] view plaincopy
  1. depends on HOTPLUG  
表示此菜单项显示与否取决于另外一个菜单项HOTPLUG ,只有当菜单项HOTPLUG这个菜单项有效显示,当前菜单项才会显示。
例如:
[html] view plaincopy
  1. config MODULES    
  2.     bool "Enable loadable module support"    
  3.    
  4. config MODVERSIONS    
  5.     bool "Set version information on all module symbols"    
  6.     depends on MODULES    
  7.    
  8.     comment "module support disabled"    
  9.     depends on !MODULES   
菜单项MODVERSIONS的显示与否取决于菜单项MODULES。这种信赖关系常用在子菜单项中。


2.3.4 选择

语法:
[html] view plaincopy
  1. choice  
  2.   
  3. 选择项  
  4.   
  5. ..  
  6.   
  7. endchoice  

2.3.5 提示

语法:
[html] view plaincopy
  1. comment "提示信息字符串"  
  2. comment选项  
comment只是用来给用户提示信息的,后跟字符串,此字符串也可以在终端中显示。
comment选项只可以是deponds on。

2.3.6 帮助

语法:
[html] view plaincopy
  1. help/---help--- <字符串>  
例如:
[html] view plaincopy
  1. config EXTRA_FIRMWARE_DIR  
  2.     string "Firmware blobs root directory"  
  3.     depends on EXTRA_FIRMWARE != ""  
  4.     default "firmware"  
  5.     help  
  6.       This option controls the directory in which the kernel build system  
  7.       looks for the firmware files listed in the EXTRA_FIRMWARE option.  
  8.       The default is the firmware/ directory in the kernel source tree,  
  9.       but by changing this option you can point it elsewhere, such as  
  10.       the /lib/firmware/ directory or another separate directory  
  11.       containing firmware files.  
help相当于注释一样,在给编辑Kconfig文件的人看的,这样可以保持其可读性.

3 举例

Kconfig:
[html] view plaincopy
  1. # drivers/Kconfig  
  2.   
  3. menu "Device Drivers"  
  4.   
  5. source "drivers/base/Kconfig"  
  6.   
  7. source "drivers/connector/Kconfig"  
  8.   
  9. source "drivers/mtd/Kconfig"  
  10. ...  
  11. endmenu  
其对应的make menuconfig界面如下图所示:
source "drivers/base/Kconfig"中的Kconfig内容如下:即对应着上图中的第一项"Generic Driver Option"的子菜单内容:
[html] view plaincopy
  1. menu "Generic Driver Options"  
  2.   
  3. config UEVENT_HELPER_PATH  
  4.     string "path to uevent helper"  
  5.     depends on HOTPLUG  
  6.     default "/sbin/hotplug"  
  7.     help  
  8.       Path to uevent helper program forked by the kernel for  
  9.       every uevent.  
  10.   
  11. config STANDALONE  
  12.     bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL  
  13.     default y  
  14.     help  
  15.       Select this option if you don't have magic firmware for drivers that  
  16.       need it.  
  17.   
  18.       If unsure, say Y.  
  19.   
  20. config PREVENT_FIRMWARE_BUILD  
  21.     bool "Prevent firmware from being built"  
  22.     default y  
  23.     help  
  24.       Say yes to avoid building firmware. Firmware is usually shipped  
  25.       with the driver, and only when updating the firmware a rebuild  
  26.       should be made.  
  27.       If unsure say Y here.  
  28.   
  29. config FW_LOADER  
  30.     tristate "Userspace firmware loading support" if EMBEDDED  
  31.     depends on HOTPLUG  
  32.     default y  
  33.     ---help---  
  34.       This option is provided for the case where no in-kernel-tree modules  
  35.       require userspace firmware loading support, but a module built outside  
  36.       the kernel tree does.  
  37.   
  38. config FIRMWARE_IN_KERNEL  
  39.     bool "Include in-kernel firmware blobs in kernel binary"  
  40.     depends on FW_LOADER  
  41.     default y  
  42.     help  
  43.       The kernel source tree includes a number of firmware 'blobs'  
  44.       which are used by various drivers. The recommended way to  
  45.       use these is to run "make firmware_install" and to copy the  
  46.       resulting binary files created in usr/lib/firmware directory  
  47.       of the kernel tree to the /lib/firmware on your system so  
  48.       that they can be loaded by userspace helpers on request.  
  49.   
  50.       Enabling this option will build each required firmware blob  
  51.       into the kernel directly, where request_firmware() will find  
  52.       them without having to call out to userspace. This may be  
  53.       useful if your root file system requires a device which uses  
  54.       such firmware, and do not wish to use an initrd.  
  55.   
  56.       This single option controls the inclusion of firmware for  
  57.       every driver which uses request_firmware() and ships its  
  58.       firmware in the kernel source tree, to avoid a proliferation  
  59.       of 'Include firmware for xxx device' options.  
  60.   
  61.       Say 'N' and let firmware be loaded from userspace.  
  62.   
  63. config EXTRA_FIRMWARE  
  64.     string "External firmware blobs to build into the kernel binary"  
  65.     depends on FW_LOADER  
  66.     help  
  67.       This option allows firmware to be built into the kernel, for the  
  68.       cases where the user either cannot or doesn't want to provide it from  
  69.       userspace at runtime (for example, when the firmware in question is  
  70.       required for accessing the boot device, and the user doesn't want to  
  71.       use an initrd).  
  72.   
  73.       This option is a string, and takes the (space-separated) names of the  
  74.       firmware files -- the same names which appear in MODULE_FIRMWARE()  
  75.       and request_firmware() in the source. These files should exist under  
  76.       the directory specified by the EXTRA_FIRMWARE_DIR option, which is  
  77.       by default the firmware/ subdirectory of the kernel source tree.  
  78.   
  79.       So, for example, you might set CONFIG_EXTRA_FIRMWARE="usb8388.bin",  
  80.       copy the usb8388.bin file into the firmware/ directory, and build the  
  81.       kernel. Then any request_firmware("usb8388.bin") will be  
  82.       satisfied internally without needing to call out to userspace.  
  83.   
  84.       WARNING: If you include additional firmware files into your binary  
  85.       kernel image which are not available under the terms of the GPL,  
  86.       then it may be a violation of the GPL to distribute the resulting  
  87.       image -- since it combines both GPL and non-GPL work. You should  
  88.       consult a lawyer of your own before distributing such an image.  
  89.   
  90. config EXTRA_FIRMWARE_DIR  
  91.     string "Firmware blobs root directory"  
  92.     depends on EXTRA_FIRMWARE != ""  
  93.     default "firmware"  
  94.     help  
  95.       This option controls the directory in which the kernel build system  
  96.       looks for the firmware files listed in the EXTRA_FIRMWARE option.  
  97.       The default is the firmware/ directory in the kernel source tree,  
  98.       but by changing this option you can point it elsewhere, such as  
  99.       the /lib/firmware/ directory or another separate directory  
  100.       containing firmware files.  
  101.   
  102. config DEBUG_DRIVER  
  103.     bool "Driver Core verbose debug messages"  
  104.     depends on DEBUG_KERNEL  
  105.     help  
  106.       Say Y here if you want the Driver core to produce a bunch of  
  107.       debug messages to the system log. Select this if you are having a  
  108.       problem with the driver core and want to see more of what is  
  109.       going on.  
  110.   
  111.       If you are unsure about this, say N here.  
  112.   
  113. config DEBUG_DEVRES  
  114.     bool "Managed device resources verbose debug messages"  
  115.     depends on DEBUG_KERNEL  
  116.     help  
  117.       This option enables kernel parameter devres.log. If set to  
  118.       non-zero, devres debug messages are printed. Select this if  
  119.       you are having a problem with devres or want to debug  
  120.       resource management for a managed device. devres.log can be  
  121.       switched on and off from sysfs node.  
  122.   
  123.       If you are unsure about this, Say N here.  
  124.   
  125. config SYS_HYPERVISOR  
  126.     bool  
  127.     default n  
  128.   
  129. endmenu  
显示效果如下图所示:

各个目录下的Kconfig文件经过最终配置,最终会在内核根目录下生成一个.config文件,这是个隐藏文件,这个文件记录着各个选项的配置及值。供Makefile文件使用.
如:
.config:
[html] view plaincopy
  1. #  
  2. # Automatically generated make config: don't edit  
  3. # Linux kernel version: 2.6.29  
  4. # Thu Dec 15 21:15:25 2011  
  5. #  
  6. CONFIG_ARM=y  
  7. CONFIG_SYS_SUPPORTS_APM_EMULATION=y  
  8. # CONFIG_GENERIC_GPIO is not set  
  9. CONFIG_GENERIC_TIME=y  
  10. CONFIG_GENERIC_CLOCKEVENTS=y  
  11. CONFIG_MMU=y  
  12. # CONFIG_NO_IOPORT is not set  
  13. CONFIG_GENERIC_HARDIRQS=y  
  14. CONFIG_STACKTRACE_SUPPORT=y  
  15. CONFIG_HAVE_LATENCYTOP_SUPPORT=y  
  16. CONFIG_LOCKDEP_SUPPORT=y  
  17. CONFIG_TRACE_IRQFLAGS_SUPPORT=y  
  18. CONFIG_HARDIRQS_SW_RESEND=y  
  19. CONFIG_GENERIC_IRQ_PROBE=y  
  20. CONFIG_RWSEM_GENERIC_SPINLOCK=y  
  21. # CONFIG_ARCH_HAS_ILOG2_U32 is not set  
  22. # CONFIG_ARCH_HAS_ILOG2_U64 is not set  
  23. CONFIG_GENERIC_HWEIGHT=y  
  24. CONFIG_GENERIC_CALIBRATE_DELAY=y  
  25. CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y  
  26. CONFIG_VECTORS_BASE=0xffff0000  
  27. CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"  


每一个CONFIG_xxx记录着之前Kconfig文件内的菜单项的值.




5.[嵌入式系統]Android 原廠-Image         build


  • 始化相關變數
    Android Makefile 參照關係是這樣的
    Makefile -> build/core/main.mk -> build/core/config.mk -> build/core/envsetup.mk -> build/core/product_config.mk
     build/core/config.mk 所進行。 build/core/envsetup.mk 檢查 developer 的設定 (buildspec.mk,並檢查執行環境,以決定輸出目錄、項目。
    build/core/config.mk 本身還依據參數,決定解譯時的相關參數。像是 compiler 的路徑、flags, lex yacc 的路徑參數等。
    關於 product 的相關設定,則是由 build/core/product_config.mk 所處理,使用 build/core/product.mk 提供之 macro 載入。根據 AndroidProduct.mk 的內容, product_config.mk 決定了
    PRODUCT_TAGSOTA_PUBLIC_KEYSPRODUCT_POLICY......
  • 偵測編譯環境和目標環境
  • 決定目標 product
  • 讀取 product 的設定
  • 讀取 product 所指定之目標平台架構設定
    • 選擇 toolchain
    • 指定編譯參數 (*-.mk)
  • 清除輸出目錄
  • 設定/檢查版本編號
  • 讀取所有 BoardConfig.mk 檔案
  • 讀取所有 module 的設定
  • 根據設定,產生必需的 rule
  • 產生 image
以上的主要流程都是由 build/core/main.mk 所安排。

沒有留言:

張貼留言