高通平臺環境搭建,編譯,系統引導流程分析

一、高通平臺android開發總結

1.1 搭建高通平臺環境開發環境php

在高通開發板上燒錄文件系統html

創建高通平臺開發環境java

高通平臺,android和 modem 編譯流程分析node

高通平臺 7620 啓動流程分析python

qcril 流程分析,設置sim卡鎖linux

python scons 語法學習android

Python 語言之 scons 工具流程分析:c++

 

1.2 搭建高通平臺環境開發環境git

高通android智能平臺概述github

選擇合適的源代碼以及工具

創建 Android 開發環境(部分略)

創建 modem 開發環境

 

1.2.1 高通android智能平臺概述

高通 7230 android 智能手機解決方案的軟件包括兩個部分

1. 以linux 操做系統爲基礎的 android 系統

2. 以 L4,REX爲基礎的 Modem 部分

在高通7系列的架構中,一個IC內部集成有兩個ARM處理器,一個ARM9(或者arm11),專門負責處理通訊協議,射頻以及GPIO等,軟件架構採用 AMSS, 另一個是ARM11,用來處理多媒體,上層應用,以及其餘的一些任務,運行的系統是 android 系統,這兩個處理器之間經過共享內存的硬件方式來進行通訊。

 

1.2.1.1 什麼是L4,REX,BREW,AMSS以及相互之間的關係

L4是一組計算機程序,是最初由Jochen Liedtke設計的微內核構架的操做系統內核,如今已經造成一個微內核家族。L4這個微內核系統因爲其出色的性能和很小的體積而開始被計算機工業所認知,被移植到了許多不一樣的硬件構架上。高通的 L4 提供了操做系統最基本的操做,是買別人的。

早期的操做系統絕大多數是 Monolithic Kernel, 意思是整個操做系統 - 包括Scheduling (調度), File system (文件系統), Networking (網絡), Device driver (設備驅動程序), Memory management (存儲管理), Paging(存儲頁面管理) - 都在內核中完成.一直到如今普遍應用的操做系統,如UNIX,Linux,和Windows還大都是monolithic kernel操做系統.但隨着操做系統變得愈來愈複雜(現代操做系統的內核有一兩百萬行C程序是很常見的事情),把全部這些功能都放在內核中使設計難度迅速增長.

微內核是一個與Monolithic Kernel相反的設計理念.它的目的是使內核縮到最小,把全部可能的功能模塊移出內核.理想狀況下,內核中僅留下Address Space Support(地址空間支持),IPC (Inter-Process Communication,進程間通信),和Scheduling(調度),其餘功能模塊作爲用戶進程運行。

REX 是在 L4 之上封裝的服務,是一個搶佔式,多任務的RTOS,全部的任務都以task的形式存在,REX提供包括任務建立,同步,互斥,計時器,中斷控制等功能的API,這裏的task實際上就是咱們的線程,每一個 task對應着一個線程。REX維護一個task list(雙向鏈表),始終運行高優先級的task。products裏面全部的服務包括3g協議棧等都是以task的形式跑在rex之上的。

而Brew的話是運行的環境,跟Java 有點兒相似,至關因而一個虛擬機。

AMSS――高級的移動用戶軟件(Advanced Mobile Subscriber Software)技術,是一種新的軟件架構,是對原來軟件架構 DMSS 的升級。 AMSS源代碼其實是QC BREW(Binary Runtime Environment For Wireless)平臺的的底層部分,去掉了爲應用程序提供接口的AEE(application execution environment)部分,高通在Dual Proc芯片上的其餘平臺基本上都是採用的這樣的架構。

 

參考文檔:

微內核操做系統及L4概述

http://wenku.baidu.com/view/90929762caaedd3383c4d311.html

MSM平臺上的AMSS

http://blog.csdn.net/yili_xie/archive/2010/01/04/5129469.aspx

 

1.2.2 選擇合適的源代碼以及工具

要編譯出可供燒寫使用的鏡像文件須要三部分代碼:

1) 獲取通過高通打補丁的 android 源代碼

2) 獲取高通針對不一樣處理器的 vendor 源代碼

3) 獲取 modem 源代碼

 

1.2.2.1 獲取通過高通打補丁的android 源代碼

網址:

https://www.codeaurora.org/wiki/QAEP#Branch_Releases

https://www.codeaurora.org/xwiki/bin/QAEP/eclair

https://www.codeaurora.org/xwiki/bin/QAEP/eclair_caramel

https://www.codeaurora.org/xwiki/bin/QAEP/froyo_almond

 

目前使用的 android 分支:

Android 2.1 版本 eclair

M7630AABBQMLZA1150 msm7630 eclair            M7630AABBQMLZA1150.xml 2010年02月01日

M7630AABBQMLZA1200 msm7630 eclair        M7630AABBQMLZA1200.xml 2010年03月30日

M7630AABBQMLZA2010 msm7630 éclair            M7630AABBQMLZA2010.xml July 02, 2010

M7630AABBQMLZA1240 msm7630 eclair_caramel  M7630AABBQMLZA1240.xml 2010年05月31日

M7630AABBQMLZA1250 msm7630 eclair_caramel  M7630AABBQMLZA1250.xml 2010年06月15日

M7630AABBQMLZA1280 msm7630 eclair_caramel  M7630AABBQMLZA1280.xml 2010年08月03日 

M76XXTSNCJNLYA5340 msm7627 eclair_chocolate M76XXTSNCJNLYA5340.xml 2010年06月04

Android 2.2 版本 froyo

M7630AABBQMLZA2020 msm7630  froyo           M7630AABBQMLZA2020.xml 2010年09月01

M76XXTSNCJNLYA6050 msm7627  froyo_almond   M76XXTSNCJNLYA6050.xml 2010年10月29日

 

如下命令獲取代碼:

https://www.codeaurora.org/xwiki/bin/QAEP/froyo_almond

ac_root=/home/shared/qualcomm

ac_root=/mnt/shared/qualcomm/

ac_date=20101105

ac_branch=froyo_almond

build_id=M76XXTSNCJNLYA6050

ac_xml=M76XXTSNCJNLYA6050.xml

mkdir -pv $ac_root/$ac_branch-$build_id-$ac_date

cd $ac_root/$ac_branch-$build_id-$ac_date

repo init -u git://codeaurora.org/platform/manifest.git -b $ac_branch -m  $ac_xml

nohup repo sync&

 

1.2.2.2 獲取高通針對不一樣處理器的vendor源代碼

根據選擇的 Android 源代碼分支不一樣, vendor 代碼的選擇也是不同的,BUILD ID 必須一致

M7630AABBQMLZA1150 對應 HY11-VR881-5.zip

M7630AABBQMLZA1250 對應 HY11-VR881-11.zip

M7630AABBQMLZA2020 對應 HY11-N1627-3.zip   AMSS 7X30 LINUX RELEASE 2.0.20

M76XXTSNCJNLYA6050 對應 HY11-N1188-6.zip   AMSS 7X27 LINUX REL 6.0.50

vendor 代碼經過有效的高通賬號登陸  HYPERLINK "https://support.cdmatech.com/login/" https://support.cdmatech.com/login/ 網站獲取

 

1.2.2.3 獲取 modem 源代碼

根據硬件配置狀況,選擇不一樣的 BUILD ID, 而後根據 BUILD ID 選擇相近的源代碼

modem 代碼經過有效的高通賬號登陸  HYPERLINK "https://support.cdmatech.com/login/" https://support.cdmatech.com/login/ 網站獲取

 

BUILD ID 是一組字母的組合,如:AAABQOLYM

如下分別對各個字段進行說明:

第三個字母 A 表示 LPDDR2    #USES_LPDDR2=yes

第三個字母 B 表示 LPDDR1

第六個字母 M 表示 Multimode

第六個字母 C 表示 CDMA

第六個字母 D 表示 JCDMA      #相對於C多了:USES_UMTS=yes USES_DSHDR_JCDMA_APIS=yes

第六個字母 O 表示 UMTS only #相對於C多了:USES_UMTS=yes USES_SUPPORT_UMTS_GPS_PROTOCOLS=yes

                              #相對於C少了:USES_CDMA=yes USES_HDR=yes USES_REL_C=yes USES_CDMA2000=yes

                              #USES_EXPORT_MCCMEID=yes USES_SUPPORT_CDMA_GPS_PROTOCOLS=yes

第7,8個字母爲 AZ  表示 NADN boot

第7,8個字母爲 LY  表示 eMMC boot  #相對於AZ多了選項: USES_SDCC_BOOT=yes USES_HSU_MS_FD_BOOT=yes

最後一個字母爲 M   表示  modem

最後一個字母爲 A   表示  app

 

以上爲 7x30 平臺的一些規律,具體參考文檔,7227 參考相應的 release note:

<<80-VR192-1_E_AMSS_Linux_Software_Users_Manual.pdf>>

第1個字母

第2個字母  F: 基於ffa參考設計 S: 基於surf的參考設計

第3個字母

第4個字母

第5個字母  K /J

K 相對於 J 多瞭如下選項

USES_HSU_CHG_BOOT=yes

USES_HSU_FAST_CHARGE=yes

USES_CHARGER=yes

USES_EBI1_TURBO_FFA=yes

第6個字母  O/ N / P

 

O表示只支持 UMTS(WCDMA)

------------------

USES_IPHC=yes                             

USES_PDCP=yes

USES_SUPPORT_UMTS_GPS_PROTOCOLS=yes

USES_UMTS=yes

-----------------

P表示只支持 CDMA/CDMA2000

USES_CDMA=yes

USES_CDMA2000=yes

USES_REL_C=yes

USES_SUPPORT_CDMA_GPS_PROTOCOLS=yes

USES_EXPORT_MCCMEID=yes

USES_HDR=yes

-----------------

N表示既支持 UMTS(WCDMA) 且支持 CDMA/CDMA2000

 

第7個字母

第8個字母

 

surf和ffa的區別

generally speaking surf have FPGA and don't have battery.

and FFA don't have FPGA but have battery.

msm7627_surf and msm7627_ffa and msm7627_7x_surf means different hardware reference design. please check with your hardware engineer on which qualcomm hardware reference you use and then select the right build command.

 

 

 

 

 

4.6 Build commands

To create an AMSS build, run the command script with the build ID matching the build

configuration desired. The command scripts may be executed from the build/ms subdirectory or

from the AMSS root directory using the full path to the command script as in the following

examples:

./AMSS/products/<asic>/build/ms/MSNCJNLYM.cmd – For SURF multimode build

./AMSS/products/<asic>/build/ms/MSNCJOLYM.cmd – For SURF UMTS only build

./AMSS/products/<asic>/build/ms/MSNCJPLYM.cmd – For SURF 1X only build

./AMSS/products/<asic>/build/ms/MFNCKNLYM.cmd – For FFA multimode and for reference only

 

以高通的開發板子爲例,看如何選擇源代碼,經過 QPST 鏈接高通的開發板,咱們能夠看到他的配置信息以下:

高通 demo 版的配置狀況:SURF-MSM7630 7X30A-AAABQMAZM-1200

從配置狀況來看只有 HY11-N0216-3_1.2.00  HY11-N0216-4_1.2.20 知足要求

HY11-N0216-3_1.2.00/AMSS/products/7x30/build/ms/AAABQMAZM.cmd

HY11-N0216-4_1.2.20/AMSS/products/7x30/build/ms/AAABQMAZM.cmd

後期咱們要跟據實際狀況來選擇 BUILD ID,如咱們的手機的配置狀況爲:

LPDDR2 ,WCDMA,eMMC 啓動(NAND備選),那麼modem 的BUILD ID爲:

AAABQOLYM 或者 AAABQOAZM

AAABQOLYM HY11-N0723-2_1.2.20/AMSS/products/7x30/build/ms/AAABQOLYM.cmd

AAABQOAZM HY11-N1122-1_1.2.20/AMSS/products/7x30/build/ms/AAABQOAZM.cmd (NABD boot 備選)

高通的Android第一人曉峯不建議咱們第一次就用eMMC,而應該用Nand,目前只有HTC在用eMMC。高通在eMMC上面提供了參考代碼,可是是未通過驗證。終端廠商在使用過程當中,必定會有不少問題須要本身解。

 

補充信息:

如今可能用到 BUILD ID 以及相應的 modem 和 vendor 源代碼。

modem代碼:

  BUILD ID              modem 源代碼        modem鏡像         說明文檔

M7630AABBQMAZM1200   HY11-N0216-3.zip  HK11-N0216-3.zip  HT11-N0216-3.zip

M7630AABBQMAZM1220   HY11-N0216-4.zip  HK11-N0216-4.zip  HT11-N0216-4.zip

--

M7630AABBQMLYM1200   HY11-N0723-1.zip  HK11-N0723-1.zip  HT11-N0723-1.zip

M7630AABBQMLYM1220   HY11-N0723-2.zip  HK11-N0723-2.zip  HT11-N0723-2.zip

--

M7630AAABQCAZM1220   HY11-N1122-1.zip  HK11-N1122-1.zip  HT11-N1122-1.zip

M7630AAABQCAZM1240   HY11-N1122-2.zip  HK11-N1122-2.zip  HT11-N1122-2.zip

M7630AAABQCAZM1250   HY11-N1122-3.zip  HK11-N1122-3.zip  HT11-N1122-3.zip

M7630AAABQCAZM1260   HY11-N1122-4.zip  HK11-N1122-4.zip  HT11-N1122-4.zip

M7630AAABQCAZM1280   HY11-N1122-5.zip  HK11-N1122-5.zip  HT11-N1122-5.zip

M7630AAABQCAZM1290   HY11-N1122-6.zip  HK11-N1122-6.zip  HT11-N1122-6.zip

--

M7630AAABQMAZM1240   HY11-N1496-2.zip  HK11-N1496-2.zip  HT11-N1496-2.zip

M7630AAABQMAZM1250   HY11-N1496-3.zip  HK11-N1496-3.zip  HT11-N1496-3.zip

 

 

80-N0216-3_B_M7630AABBQMAZM1200.pdf

5.3.2.1 LPDDR1 NAND boot Multimode              AABBQMAZM.cmd

5.3.2.2 LPDDR1 eMMC boot Multimode              AABBQMLYM.cmd

5.3.2.3 LPDDR1 eMMC boot UMTS only              AABBQOLYM.cmd

5.3.2.4 LPDDR1 NAND boot JCDMA                  AABBQDAZM.cmd

5.3.2.5 LPDDR2 NAND boot Multimode              AAABQMAZM.cmd

5.3.2.6 LPDDR2 eMMC boot Multimode              AAABQMLYM.cmd

 

80-N0216-4_A_M7630AABBQMAZM1220.pdf

5.3.2 Build instructions and commands

5.3.2.1 LPDDR1 NAND boot Multimode              AABBQMAZM.cmd

5.3.2.2 LPDDR1 eMMC boot Multimode              AABBQMLYM.cmd

5.3.2.3 LPDDR1 eMMC boot UMTS only              AABBQOLYM.cmd

5.3.2.4 LPDDR1 NAND boot JCDMA                  AABBQDAZM.cmd

5.3.2.5 LPDDR2 NAND boot Multimode              AAABQMAZM.cmd

5.3.2.6 LPDDR2 eMMC boot Multimode              AAABQMLYM.cmd

5.3.2.7 LPDDR2 eMMC boot UMTS only              AAABQOLYM.cmd

5.3.2.8 LPDDR2 NAND boot C2K Only               AAABQCAZM.cmd

5.3.2.9 LPDDR1 eMMC boot C2K Only               AABBQCLYM.cmd

5.3.2.10 LPDDR2 NAND boot JCDMA                 AAABQDAZM.cmd

5.3.2.11 LPDDR2 NAND boot UMTS only             AAABQOAZM.cmd

 

 

80-N1665-1_B_M7630AAABQ_AZM1240.pdf

5.3.2 Build instructions and commands

5.3.2.1 LPDDR1/LPDDR2 eMMC boot Multimode      AABBQMLYM.cmd

5.3.2.2 LPDDR1/LPDDR2 eMMC boot UMTS only      AABBQOLYM.cmd

5.3.2.3 LPDDR1/LPDDR2 eMMC boot C2K only       AABBQCLYM.cmd

5.3.2.4 LPDDR2/LPDDR1 NAND boot Multimode      AAABQMAZM.cmd

5.3.2.5 LPDDR1/LPDDR2 NAND boot JCDMA          AABBQDAZM.cmd

5.3.2.6 LPDDR2/LPDDR1 NAND boot C2K only       AAABQCAZM.cmd

5.3.2.7 LPDDR2/LPDDR1 NAND boot UMTS only      AAABQOAZM.cmd

The same build ID will now work for LPDDR1 as well as LPDDR2.

從以上的發佈信息,只有 LPDDR2 和 LPDDR1 不一樣的狀況下能夠使用同一個 build ID。

對於咱們的硬件配置狀況(LPDDR2 eMMC boot UMTS only) 能夠使用的編譯命令文件爲:

AAABQOLYM.cmd  AABBQOLYM.cmd

選擇 modem 代碼 M7630AAABQMAZM1250  HK11-N1496-3.zip

 

若是是支持 BREW 平臺,一般多下面的選項:

USES_BREW_4.0=yes

USES_BREW=yes

USES_BREW_APPMGR=yes

或者 USES_BREW_USB_HID=yes

沒有 USES_DIAG_SMD_SUPPORT=yes

 

項目 PD1007

OEM/Target Equipment (FeaturePhone,Smartphone,Datacard): Smartphone

Anticipated Launch Date: April 1 2011

Target market (such as China Telecom): China Open market

Current Software (such as Q6270BKPRZL1505):  froyo-M76XXTSNCJNLYA7010

Bluetooth IC/Module (vendor name and module if support BT): BTS4025

WLAN IC/Module (vendor and module if support WLAN ):WCN1312

Chipset (such as QSC6270):MSM7227-1

RF chipset (such as RGR6240):RTR6285

PMIC chipset (such as PM7540):PM7540

WCMDA Supported Bands (900,1900,2100…. if support WCDMA):2100

CMDA Supported Bands (450,850,1900,2100… if support CDMA ):not suport

OS (Brew,BMP,Android,WM,ThinUI(no UI)…):android froyo

OS version (Android Donuts…): android froyo

 

1.2.2.3.1 高通 modem 源代碼編譯前的修正

從高通獲取的源代碼直接編譯會存在一些問題,如下爲可能的問題以及解決方法:

1) 爲相應的腳本加上編譯選項

vim ./AMSS/products/7x30/build/ms/xxxxxx.cmd

加上: BUILD_UNIX=yes

 

2) 若是編譯過程出現 .pl 文件沒有執行權限而退出,那麼爲工程下面全部的 pl 文件加上可執行屬性,命令:

find ./ -name "*.pl" |xargs chmod  755

 

3) 沒法找到須要的 pl 腳本解析器

vim ./AMSS/products/7x30/tools/build/depgen.pl

修改

#!/pkg/perl/5.6.1/bin/perl -w

#!/usr/bin/perl -w

 

4) 若是出現錯誤: "AMSS/products/7x30/core/bsp/build/data/incpathsaaabqmlym.py", line 14

IndentationError: expected an indented block

修改文件:./AMSS/products/7x30/core/bsp/build/scripts/genpaths.pl 內容:

#if ($line =~ /^# makefile \(from/)

爲:

if ($line =~ /^# makefile /)

緣由分析:

genpaths.pl 會對編譯過程的中間信息 :

...

line=# makefile (from'incpaths.min',line 363)

line=QVPCODEC_AUDIOINC = $(QVPCODEC)/audio/inc

...

等信息進行解析,因爲咱們使用的是中文系統,因此以上內容變爲:

line=# makefile (從'incpaths.min',行 363)

line=QVPCODEC_AUDIOINC = $(QVPCODEC)/audio/inc

因此致使:

#if ($line =~ /^# makefile \(from/) 判斷條件爲爲 false

沒法正確生成  incpathsaaabqmlym.py,python 在解析該文件的時候認爲存在語法錯誤。

 

 

在 modem 代碼 M7630AABBQMAZM2020(HY11-N2280-2.zip)中開始使用 genincpaths.py 產生

./AMSS/products/7x30/core/bsp/build/data/incpathsaaabqoazm.py 文件,因此修改文件

amend-source-code-qualcomm-modem.sh 在腳本中須要加入如下內容:

incpathsxxx_py=$PRODUCT_DIR/core/bsp/build/scripts/genincpaths.py

if test -f $incpathsxxx_py; then

    PERL=`which /usr/bin/perl`

    sed -i "s/(from//g" $incpathsxxx_py

fi

./AMSS/products/7x30/multimedia/audio/drivers/Adie/AdieCodecDb/src/DALAdieCodecDb.c

#DalAdieCodecDbInternal.h 改成:

#include "DALAdieCodecDbInternal.h"

 

5) 若是出現 make: execvp: ../../../../platform/cs/bin/cifc: Permission denied 錯誤,執行如下命令:

chmod -R 755 AMSS/platform/cs/bin/*

 

 

1.2.3 創建 Android 開發環境

(略)

curl http://android.git.kernel.org/repo >~/bin/repo

chmod a+x ~/bin/repo

export PATH=~/bin:$PATH

1) 安裝基本軟件

sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl sun-java5-jdk zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev ia32-libs x11proto-core-dev libx11-dev lib32readline5-dev lib32z-dev

 

2) 安裝 sun-java5-jdk

ubuntu 下經過命令: sudo apt-get install sun-java5-jdk 將會安裝下面的包

sun-java5-bin sun-java5-demo sun-java5-jdk sun-java5-jre sun-java5-plugin

若是ubuntu 發佈版本中沒有 sun-java5-jdk 那麼

sudo vim /etc/apt/source.list

#for sun-java5-jdk

deb http://us.archive.ubuntu.com/ubuntu/ jaunty multiverse

deb http://us.archive.ubuntu.com/ubuntu/ jaunty-updates multiverse

sudo apt-get update

sudo apt-get sun-java5-jdk

或者,若是 ubuntu 版中不支持 apt-get ,那麼用手動安裝:

sudo mount -t nfs  172.20.127.15:/home/shared /mnt

sudo dpkg -i /mnt/tools/debs/java-1.5.0-sun/sun-java5-*

 

3) 配置usb

cd /etc/udev/rules.d/

sudo vi 50-android.rules

# adb single interface device

SUBSYSTEM=="usb_device", SYSFS{idVendor}=="18d1", SYSFS{idProduct}=="d00d",

MODE="0664", GROUP="plugdev"

# adb composite interface device

SUBSYSTEM=="usb_device", SYSFS{idVendor}=="18d1", SYSFS{idProduct}=="deed",

MODE="0664", GROUP="plugdev"

# Sooner low-level bootloader

BUS=="usb", SYSFS{idVendor}=="0bb4", SYSFS{idProduct}=="0a51",

MODE="0664",GROUP="plugdev"

sudo /etc/init.d/udev restart

 

1.2.4 創建 modem 開發環境

與android 源代碼不一樣,modem 編譯工具使用的是 RVDS ,實際上只用到其中的 RVCT 編譯器, 高通不提供該工具,咱們必須從arm公司獲取相應的受權,RVDS 是 ADS 的升級版本,從 ADS 1.2 開始到 RVDS 3.1 咱們公司都有其受權,按照高通的要求咱們目前必須使用 RVDS 2.2 而且使用他的 349 patch。

RVDS 2.2 安裝以及使用步驟以下:

1). RVDS 2.2 共享在 172.20.127.15:/home/shared/ 目錄

sudo mount -t nfs 172.20.127.15:/home/shared/ /mnt

cd /mnt/qualcommon/RVDS-2.2/

linux下rvds2.2的安裝程序爲:

./rvds2.2_linux-pentium/setuplinux.bin

執行以上命令,按照默認步驟安裝,安裝路徑爲:~/ARM

注意事項:

安裝過程若是出現錯誤:

..................java.lang.UnsatisfiedLinkError: /tmp/ismp001/6073753.tmp: libstdc++-libc6.2-2.so.3:

cannot open shared object file: No such file or directory

從網上下載 libstdc++-libc6.2-2.so.3 拷貝到 /usr/lib 目錄 ,或者從下面地址獲取:

http://172.20.127.15/repositories/DocsAndTools/Tools/Qualcomm/RVDS-2.2-patch/patch/libstdc++-libc6.2-2.so.3

工具的安裝經過腳本進行了簡化,具體過程請參考文檔:

80-N0216-2_A_M7630AABBQMAZM1170.pdf

80-VR881-7_B_M7630AABBQMLZA1200.pdf

80-VR192-1_C_AMSS_Linux_Software_Users_Guide.pdf

80-VR192-1_D_AMSS_Linux_Software_Users_Guide.pdf

 

2) 安裝高通指定的 593 patch

cd /mnt/qualcommon/RVDS2.2/下執行命令:

./setup-patch-rvct2.2-bin593-lib349.sh

 

目前版本只支持 32 位的系統

1.2.4.1 補充

vim ./AMSS/products/7x30/core/bsp/build/scripts/defaults.py 定義了工做線程

  #num_jobs = num_cpu * 2 modified by mhf

   num_jobs = 2

   if num_jobs < 4:

      num_jobs = 2

   if num_jobs > 8:

      num_jobs = 8

   env.SetOption('num_jobs', num_jobs)

―――――――

獲取 RVDS

官方網站下載評估版本

https://silver.arm.com/browse

http://www.arm.com/products/tools/software-development-tools.php

https://silver.arm.com/download/eval_download.tm

https://silver.arm.com/userguides/Web_Licensing_Portal_User_Guide.pdf (Licensing 須要經過 host id 註冊)

―――――――

1.2.4.1.1 獲取 licenses

RVDS 的 licenses 從其官方網站獲取

https://silver.arm.com/licensing/

https://silver.arm.com/licensing/generate.tm

http://www.keil.com/support/man/docs/license/license_sul_install.htm

 

入口 https://silver.arm.com/licensing/ 合法用戶登陸

用戶名: mohuifu@gmail.com  密碼: Mohuifu7737

入口 https://silver.arm.com/licensing/generate.tm 輸入產品的序列號

而後按照步驟一步步操做便可

Server Host Id Type 類型選擇 ETHERNET

Server Host Id 填寫須要綁定主機的MAC地址 00:1a:64:0a:ba:70

最後保存 license.dat 文件,文本格式。

 

 

1.2.4.1.2 Flex 簡單使用指南

FLEXlm是應用普遍的License管理工具,它以使軟件License可以在網上浮動而出名。浮動的License有利於軟件的使用和對 License的管理,這使得用戶可以高效地使用有效的許可,並使管理者可以控制容許使用它的節點。因爲有大約1500廠商使用FLEXle管理 lICENSE,因此CAD系統管理人員極有可能要同時安裝和管理來自不一樣廠商的License或同一廠商多個產品的License文件。可採起如下方法避免產生衝突:

  (1)用一個服務器運行一個Lmgrd(License文件的後臺管理程序)和多個License文件;

  (2)用一個服務器運行多個Lmgrd和License文件;

  (3)運用多個服務器節點,每一個服務器運行單獨的Lmgrd和License文件。

  第一種選擇主要造用於高版本的Lmgrd,V6以前和FLEXlm,每一個Lmgrd只能管理一個License文件;

  第二種選擇,將使用一臺服務器,但須要運行多個Lmgrd;第三種選擇,必須使用多個License服務器。

  1、服務器端設定

  1.License文件的設定

  在使用FLEXlm進行管理的License文件中通常有SERVER行,它經過SERVER行的hostname和hostID定義License服務器。

   SERVER this_host 0050BB0F402 27000

   hostname hostID post

 

  2.服務方式的選擇

  (1)一個服務器運行一個Lmgrd和多個License文件若是多個License文件具備相同的hostID,則能夠經過修改hostname進行合併。合併時,首先將多個License文件加到一個文件中,而後修改SERVER行,而且只保留一個SERVER行。對於Windows NT操做系統,應在各License的默認位置保存一個合併後的備份,這樣每一個軟件將在其默認位置找到License信息,從而避免了對 LM_LICENSE_FILE的設定;對於UNIX操做系統,能夠創建一個默認位置到License存放位置和Link。合併後的License文件,就能夠使用同一個Lmgrd。

  (2)一個服務器運行一個Lmgrd和一個別License文件若是HostID不同,則這些License服務只能運行於不一樣的服務器節點上,而且License不能合併。能夠選擇使用一個服務器運行一個Lmgrd和License文件。

  (3)一個服務器運行多個Lmgrd和License文件若是多個License未進行合併,能夠經過在同一臺機器上啓動多個Lmgrd,每一個 Lmgrd管理一個License文件。使用多個Lmgrd管理多個License文件對服務器的性能並無明顯影響。若是License是由不一樣版本的 FLEXlm產生的,通常是新版本能夠管理舊版本的License文件。因此應使用最新的Lmgrd和Vendor daemon。另外,當用一個服務器的多個Lmgrd管理多個License文件時,應該注意任何二個License文件的post都不能同樣,而且對於每一個License而言,應選用合造的Lmgrd。

 

  2、客戶端設定

  當使用客戶端應用程序時(a Licensedapplication),能夠經過在系統的環境變量中設定LM_LICENSE_FILE,使Application可以指向不一樣服務器上的License文件。若是要使a Licensed application使用不一樣服務器都有單獨的一個License文件),客戶端應將須要用到的License文件拷貝到本機目錄下,並指定LM_LICENSE_FILE環境變量。UNIX: %setenv LM_LICENSE_FILE lfpath1 : lfpath2 :…… : lfpathN Windows: lfpath1 ;lfpath2:…… ;lfpathN LfpathN爲第N個License的路徑;UNIX下路徑間用":"隔開;Windows/NT下路徑間使用";"隔開;

  這樣,每一個Licensed aplication在啓動時將依次查詢LM_LICENSE_FILE中所指定的License文件,並向相應的License服務器申請許可,以使用戶能從所列的服務器獲得許可。LM_LICENSE_FILE也能夠使用各License文件中所指定的"post@hostname"。下面以Windows NT爲例介紹多個FLEXlm的安裝。

 

  3、同一機器上多個FLEXlm License Server的安裝

  (1) 以Administrator身分登陸;

  (2)在C盤建C:\FLEXlm目錄,並拷貝相關文件到其下;

  (3)在C:\FLEXlm下創建欲安裝License Server的軟件目錄,放置各軟件的License文件,Daemon和Daemon所需的動態鏈接庫;

  (4)修改License.dat和SERVER行和DAEMON的位置,並啓動FLEXlm License Manager。    

  (5)在Setup修改Service Name,輸入造當名稱,以區別是何種License服務;利用Browse選擇合適Lmgrd.exe和對應和License.dat並指定Debug.log和放置路徑;

  (6)選中"StartServer at Power-Up"與"Use NT Services",這樣下次啓動機器時,將自動啓動該Li-cense服務;

  (7)點擊Control按鈕檢查Service Name是否與設定名稱相同,若是不一樣,回到"Setup"從新選擇Service Name;若是同樣,點擊"Start"啓動該Li-cense Server;點擊"Status"檢查Licevse Server啓動狀況,若出現Server_name: License server UP (MASTER),表示License Server啓動成功;

  (8)安裝另外的License Server:可依上述(3)~(7)從新執行一次便可;

  (9)切換不一樣License Server:在"Setup"中選擇適當的"Service Name",而後啓動或中止相應的License服務;

  (10)移除License Server:在"Setup"選擇適當的"Service Name",而後按"Remove"便可。

 

 

1.2.4.1.3 啓動 license 服務器

#!/bin/bash

ac_PATH=~/ARM/Utilities/FLEXlm/9.2/release/linux-pentium/

PATH=${ac_PATH}:${PATH}

export PATH

LICENSE_FILE=~/ARM/licenses/license.dat

LOG=~/ARM/licenses/license.log

case "$1" in

start)

    lmgrd -c ${LICENSE_FILE} 2>> ${LOG} 1>&2

    echo -n " lmgrd"

    ;;

stop)

    ac_pid=`pidof lmgrd`

    kill $ac_pid 2>> ${LOG} 1>&2

    ac_pid=`pidof armlmd`

    kill $ac_pid 2>> ${LOG} 1>&2

    #lmgrd -c ${LICENSE_FILE} -x lmdown 2>> ${LOG} 1>&2

    ;;

*)

    echo "Usage: `basename $0` {start|stop}" 1>&2

    exit 64

    ;;

esac

 

1.2.4.1.4 license 沒有辦法從服務器獲取的幾種狀況

    1.須要關閉網絡防火牆

    2.在客戶端須要配置license服務器的服務端口

    3.要求在同一個局域網內

sudo ufw disable

防火牆在系統啓動時自動禁用

sudo iptables -A OUTPUT -p tcp --dport 8224 -j ACCEPT

修改/etc/sysconfig/iptables 文件,添加如下內容:

-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 23 -j ACCEPT

 

1.2.4.1.5 破解 rvds 的license

第 1 章 歡迎使用 FLEXlm

在linux下建立一個虛擬網卡

http://nxjsjx.com/cgl/%E8%BD%AF%E4%BB%B6/%E5%A4%9A%E5%AA%92%E4%BD%93%E5%88%B6%E4%BD%9C%E8%BD%AF%E4%BB%B6/flash/Autocad%202002/Netsetup/support/AdLM/Docs/FlexUser/all.htm#895035

 

1.2.5 在高通開發板上燒錄文件系統

經過設置模塊完成系統,應用程序等個性化設置。

燒錄以前必須瞭解獲取硬件配置狀況

2. 由硬件配置狀況到高通網站選擇相應的鏡像文件

3. 燒錄鏡像文件到高通demo開發板

4. 從高通網站下載源代碼編譯相應的鏡像文件進行驗證

 

1. 燒錄以前必須瞭解獲取硬件配置狀況

高通 demo 板的配置狀況:SURF-MSM7630 7X30A-AAABQMBZM-1090  或者 7X30A-AAABQMAZM-1200

以上信息能夠經過 QPST 鏈接高通的demo開發板得到

 

2. 由硬件配置狀況到高通網站選擇相應的鏡像文件

要給高通的開發板燒錄文件系統,必須有如下的鏡像文件:

adsp.mbn           dsp相關的

amss.mbn           AMSS modem binary image

dbl.mbn            設備啓動的裝載程序

osbl.mbn           OS boot loader binary image

partition.mbn      分區表的二進制文件

appsboot.mbn       應用程序的啓動文件,若是是 eMMC 啓動對應文件 emmc_appsboot.mbn

boot.img           ap 端的linux 內核

system.img         android 文件系統的 system 分區

userdata.img       android 文件系統的 data 分區

其中 adsp.mbn,amss.mbn,dbl.mbn,osbl.mbn,partition.mbn 能夠從如下目錄獲取

unzip /home/shared/qualcommon/HK11-N0216-3.zip

unzip /home/shared/qualcommon/HK11-N0216-4.zip

HK11-N0216-3_1.2.00/AAABQMAZ/

HK11-N0216-4_1.2.20/AAABQMAZ/

appsboot.mbn,boot.img,system.img,userdata.img 必須來自eclair源代碼

 

3. 燒錄鏡像文件到高通demo開發板

怎樣燒寫文件請參考工具使用文檔

經過fastboot燒寫 boot.img syste.img usrdata.img

參考文檔:

80-VR192-1_D_AMSS_Linux_Software_Users_Guide.pdf

6.2 USB setup in Linux

6.2.1 Using Fastboot in Linux

 

 

4. 從高通網站下載源代碼編譯相應的鏡像文件進行驗證

高通有兩個cpu,他們分別跑不一樣的系統,應用程序(ap)端是android系統,modem 端是高通本身的系統。

======

android 系統目前使用的是 eclair 版本,此版原本自標準的 android 2.1 eclair,高通在上面加了本身的補丁,代碼網址:

https://www.codeaurora.org/wiki/QAEP#Branch_Releases

https://www.codeaurora.org/wiki/QLBEP

下載 M7630AABBQMLZA1150 分支:

February 1, 2010    M7630AABBQMLZA1150    msm7630    eclair    M7630AABBQMLZA1150.xml

命令以下:

mkdir  -pv ~/workspace/gphone/eclair-M7630AABBQMLZA1150-20100201

cd ~/workspace/gphone/eclair-M7630AABBQMLZA1150-20100201

repo init -u git://codeaurora.org/platform/manifest.git  -b eclair -m M7630AABBQMLZA1150.xml

nohup repo sync

代碼下的 vendor/qcom-proprietary 來自包 HY11-VR881-5.zip

以上兩部分代碼已經下載而且合併,共享在:

http://172.20.127.15/repositories/TD1002/trunk/eclair-M7630AABBQMLZA1150

---------------

編譯 eclair 代碼

svn co http://172.20.127.15/repositories/TD1002/trunk/eclair-M7630AABBQMLZA1150

cd eclair-M7630AABBQMLZA1150

cd eclair-M7630AABBQMLZA1150$

. ./setenv.sh

. ./make-image.sh

 

=======

modem代碼從高通網站:https://support.cdmatech.com/login/ 上獲取

咱們目前使用的是:

共享在:

http://172.20.127.15/repositories/TD1002/trunk/modem-M7630AABBQMAZM1220

-------

編譯 modem 代碼

svn co http://172.20.127.15/repositories/TD1002/trunk/modem-M7630AABBQMAZM1220

cd modem-M7630AABBQMAZM1220

. ./setenv-qualcomm.sh

. ./make

========

編譯結果分別以下:

------------

其中 adsp.mbn,amss.mbn,dbl.mbn,osbl.mbn,partition.mbn 位於如下目錄:

./modem-M7630AABBQMAZM1220/AMSS/products/7x30/build/ms/bin/AAABQMAZ/adsp.mbn

./modem-M7630AABBQMAZM1220/AMSS/products/7x30/build/ms/bin/AAABQMAZ/amss.mbn

./modem-M7630AABBQMAZM1220/AMSS/products/7x30/build/ms/bin/AAABQMAZ/dbl.mbn

./modem-M7630AABBQMAZM1220/AMSS/products/7x30/build/ms/bin/AAABQMAZ/osbl.mbn

./modem-M7630AABBQMAZM1220/AMSS/products/7x30/build/ms/bin/AAABQMAZ/partition.mbn

------------

appsboot.mbn,boot.img,system.img,userdata.img 位於如下目錄:

./eclair-M7630AABBQMLZA1150/out/target/product/msm7630_surf/appsboot.mbn

./eclair-M7630AABBQMLZA1150/out/target/product/msm7630_surf/boot.img

./eclair-M7630AABBQMLZA1150/out/target/product/msm7630_surf/system.img

./eclair-M7630AABBQMLZA1150/out/target/product/msm7630_surf/userdata.img

./eclair-M7630AABBQMLZA1150/out/target/product/msm7630_surf/system.img.ext3

./eclair-M7630AABBQMLZA1150/out/target/product/msm7630_surf/userdata.img.ext3

------------

eMMC 啓動使用的是 ext3 文件系統,須要使用鏡像 system.img.ext3 userdata.img.ext3

補充說明:

partition.mbn 文件的原始數據來自配置文件:

./AMSS/products/7x30/tools/jsdcc/partition_load_pt/partition.xml

 

 

1.3 高通平臺,android和 modem 編譯流程分析

android 代碼編譯流程分析

modem 代碼編譯流程分析

1.3.1 android代碼編譯流程分析

1.  從服務器下載 android 源碼到當前目錄

http://smartphone/repositories/TD1014/branch/froyo_almond-M76XXTSNCJNLYA6050-drivers/

svn co http://172.20.127.15/repositories/TD1014/trunk/froyo_almond-M76XXTSNCJNLYA6050/

cd froyo_almond-M76XXTSNCJNLYA6050/

. ./setenv.sh  設置環境變量

Setting Environment ...

一般狀況下 generic 用於編譯模擬器版本

Options are:

     1. generic

     2. msm7627_surf

     3. msm7627_ffa

     4. tiny-system

====從以上列表中選擇====

Which would you like? [1]

 

燒錄的鏡像文件appsboothd.mbn  appsboot.mbn boot.img system.img userdata.img persist.img 來自 android 源碼

appsboot.mbn 的主要功能是裝載 linux 內核,經過 linux 的引導來完成 android 系統的加載,

appsboot.mbn 被燒寫在相應的分區,它的加載由 osbl.mbn 來完成, osbl.mbn 程序來自 modem。

7x30 7x27 系列 appsboot 不同,7x30 的 appsboot.mbn 是 7x27 appsboothd.mbn  appsboot.mbn 兩個文件的合併

 

1) appsboot.mbn 生成過程解析

2) boot.img 生成過程解析,怎樣手動生成 boog.img

 

1.3.1.1 編譯工具檢測

make out/target/product/msm7630_surf/appsboot.mbn

1.3.1.1.1  

1.3.1.2 appsboot.mbn 生成過程解析

make out/target/product/msm7630_surf/appsboot.mbn

make out/target/product/msm7630_surf/nandwrite

make out/target/product/msm7630_surf/emmc_appsboot.mbn

分別執行:

make -C bootable/bootloader/lk BOOTLOADER_OUT=../../.././out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ msm7630_surf

make -C bootable/bootloader/lk BOOTLOADER_OUT=../../.././out/target/product/msm7630_surf/obj/nandwrite msm7630_surf_nandwrite BUILD_NANDWRITE=1

make -C bootable/bootloader/lk BOOTLOADER_OUT=../../.././out/target/product/msm7630_surf/obj/BOOTLOADER_EMMC_OBJ msm7630_surf EMMC_BOOT=1

 

生成 nandwrite

===============

#build nandwrite as a part of Android Build

TARGET_NANDWRITE := $(PRODUCT_OUT)/obj/nandwrite/build-$(TARGET_PRODUCT)_nandwrite/lk

NANDWRITE_OUT := $(TOP)/$(TARGET_OUT_INTERMEDIATES)/nandwrite

 

nandwrite_clean:

    $(hide) rm -f $(TARGET_NANDWRITE)

    $(hide) rm -rf $(NANDWRITE_OUT)

 

$(NANDWRITE_OUT):

    mkdir -p $(NANDWRITE_OUT)

 

$(TARGET_NANDWRITE): nandwrite_clean $(NANDWRITE_OUT)

    @echo $(TARGET_PRODUCT)_nandwrite

    $(MAKE) -C bootable/bootloader/lk BOOTLOADER_OUT=../../../$(NANDWRITE_OUT) $(TARGET_PRODUCT)_nandwrite BUILD_NANDWRITE=1

================

 

vim ./bootable/bootloader/lk/makefile:98:

TARGET   := msm7630_surf  #./bootable/bootloader/lk/project/msm7630_surf.mk

PLATFORM := msm7x30       #./bootable/bootloader/lk/target/msm7630_surf/rules.mk

msm7x30

msm7630_surf.mk

msm7630_surf_nandwrite

=============================

include project/$(PROJECT).mk

include target/$(TARGET)/rules.mk

include target/$(TARGET)/tools/makefile

include platform/$(PLATFORM)/rules.mk

include arch/$(ARCH)/rules.mk

include platform/rules.mk

include target/rules.mk

include kernel/rules.mk

include dev/rules.mk

include app/rules.mk

...

include make/module.mk

...

include make/build.mk

========================

vim bootable/bootloader/lk/make/module.mk

INCMODULES := $(MODULES)

$(info including $(INCMODULES))

include $(addsuffix /rules.mk,$(INCMODULES))

展開爲:

./bootable/bootloader/lk/app/nandwrite/rules.mk

./bootable/bootloader/lk/dev/fbcon/rules.mk

./bootable/bootloader/lk/dev/keys/rules.mk

./bootable/bootloader/lk/lib/debug/rules.mk

./bootable/bootloader/lk/lib/heap/rules.mk

./bootable/bootloader/lk/lib/libc/rules.mk

./bootable/bootloader/lk/lib/ptable/rules.mk

========================

bootable/bootloader/lk/make/build.mk:29:

include arch/$(ARCH)/compile.mk

 

 

./bootable/bootloader/lk/project/msm7630_surf_nandwrite.mk 中有:

MODULES += app/nandwrite

./bootable/bootloader/lk/platform/msm7x30/rules.mk中有:

MODULES += dev/fbcon

./bootable/bootloader/lk/kernel/rules.mk 中有:

MODULES += lib/libc lib/debug lib/heap

./bootable/bootloader/lk/target/msm7630_surf/rules.mk 中有:

MODULES += dev/keys lib/ptable

因此:

MODULES= app/nandwrite dev/fbcon dev/keys lib/debug lib/heap lib/libc lib/ptable

 

 

由於

ifeq ($(BUILD_NANDWRITE), 1)

    APPSBOOTHDR_FILES :=

  else

out/host/linux-x86/bin/acp -fpt out/target/product/msm7630_surf/obj/nandwrite/build-msm7630_surf_nandwrite/lk out/target/product/msm7630_surf/nandwrite

 

 

  25780     184   34000   59964    ea3c ../../.././out/target/product/msm7630_surf/obj/nandwrite/build-msm7630_surf_nandwrite/lk

arm-eabi-objcopy -O binary ../../.././out/target/product/msm7630_surf/obj/nandwrite/build-msm7630_surf_nandwrite/lk ../../.././out/target/product/msm7630_surf/obj/nandwrite/build-msm7630_surf_nandwrite/lk.bin

generating listing: ../../.././out/target/product/msm7630_surf/obj/nandwrite/build-msm7630_surf_nandwrite/lk.lst

generating listing: ../../.././out/target/product/msm7630_surf/obj/nandwrite/build-msm7630_surf_nandwrite/lk.debug.lst

generating symbols: ../../.././out/target/product/msm7630_surf/obj/nandwrite/build-msm7630_surf_nandwrite/lk.sym

generating size map: ../../.././out/target/product/msm7630_surf/obj/nandwrite/build-msm7630_surf_nandwrite/lk.size

make[2]:正在離開目錄 /opt/workspace/gphone/qualcomm/eclair-M7630AABBQMLZA1150/bootable/bootloader/lk

make[1]:正在離開目錄 /opt/workspace/gphone/qualcomm/eclair-M7630AABBQMLZA1150/bootable/bootloader/lk

target Prebuilt:  (out/target/product/msm7630_surf/nandwrite)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

make -C bootable/bootloader/lk BOOTLOADER_OUT=./out/target/product/msm7630_surf/obj/nandwrite msm7630_surf_nandwrite BUILD_NANDWRITE=1

 

make[2]: 正在進入目錄 `/opt/workspace/gphone/qualcomm/eclair-M7630AABBQMLZA1150/bootable/bootloader/lk`

msm7630_surf_nandwrite

make -C bootable/bootloader/lk BOOTLOADER_OUT=../../.././out/target/product/msm7630_surf/obj/nandwrite msm7630_surf_nandwrite BUILD_NANDWRITE=1

==》生成 mkheader 工具

gcc target/msm7630_surf/tools/mkheader.c -o target/msm7630_surf/tools/mkheader

 

$(BUILDDIR)/system-onesegment.ld: $(LOCAL_DIR)/system-onesegment.ld

    @echo generating $@

    @$(MKDIR)

    $(NOECHO)sed "s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/" < $< > $@

 

 

generating ../../.././out/target/product/msm7630_surf/obj/nandwrite/build-msm7630_surf_nandwrite/system-onesegment.ld

compiling arch/arm/crt0.S

compiling arch/arm/crt0.S

。。。compiling lib/ptable/ptable.c

compiling lib/ptable/ptable.c

 

vim bootable/bootloader/lk/platform/msm7x30/rules.mk

-----

LINKER_SCRIPT += $(BUILDDIR)/system-onesegment.ld

include platform/msm_shared/rules.mk

-----

 

./build/core/product_config.mk:177:TARGET_DEVICE := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEVICE)

./build/core/envsetup.mk:152:OUT_DIR := $(TOPDIR)out

./build/core/envsetup.mk:159:TARGET_OUT_ROOT_release := $(OUT_DIR)/target

./build/core/envsetup.mk:161:TARGET_OUT_ROOT := $(TARGET_OUT_ROOT_$(TARGET_BUILD_TYPE))

./build/core/envsetup.mk:178:  TARGET_PRODUCT_OUT_ROOT := $(TARGET_OUT_ROOT)/product

./build/core/envsetup.mk:184:PRODUCT_OUT := $(TARGET_PRODUCT_OUT_ROOT)/$(TARGET_DEVICE)

build/core/envsetup.mk:200:TARGET_OUT_INTERMEDIATES := $(PRODUCT_OUT)/obj

bootable/bootloader/lk/AndroidBoot.mk:4:BOOTLOADER_OUT := $(TOP)/$(TARGET_OUT_INTERMEDIATES)/BOOTLOADER_OBJ

bootable/bootloader/lk/makefile:32:BUILDDIR := $(BOOTLOADER_OUT)/build-$(PROJECT)

bootable/bootloader/lk/makefile:34:OUTELF := $(BUILDDIR)/lk

因此:

TARGET_PRODUCT_OUT_ROOT=out/target/product/

PRODUCT_OUT=out/target/product/msm7630_surf/

TARGET_OUT_INTERMEDIATES=out/target/product/msm7630_surf/obj/

BOOTLOADER_OUT=out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/

因此:

BUILDDIR=out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf

因此:

OUTELF=out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk

 

 

make -C bootable/bootloader/lk BOOTLOADER_OUT=../../.././out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ msm7630_surf

 

 

bootable/bootloader/lk/makefile

OUTELF := $(BUILDDIR)/lk

./bootable/bootloader/lk/make/build.mk

$(OUTELF): $(ALLOBJS) $(LINKER_SCRIPT)

    @echo linking $@

    $(NOECHO)$(LD) $(LDFLAGS) -T $(LINKER_SCRIPT) $(ALLOBJS) $(LIBGCC) -o $@

 

 

 

vim ./bootable/bootloader/lk/AndroidBoot.mk

TARGET_NANDWRITE := $(PRODUCT_OUT)/obj/nandwrite/build-$(TARGET_PRODUCT)_nandwrite/lk

$(TARGET_NANDWRITE): nandwrite_clean $(NANDWRITE_OUT)

    @echo $(TARGET_PRODUCT)_nandwrite

    $(MAKE) -C bootable/bootloader/lk BOOTLOADER_OUT=../../../$(NANDWRITE_OUT) $(TARGET_PRODUCT)_nandwrite BUILD_NANDWRITE=1

 

BOOTLOADER_EMMC_OUT := $(TOP)/$(TARGET_OUT_INTERMEDIATES)/BOOTLOADER_EMMC_OBJ

 

 

 

vim ./bootable/bootloader/lk/make/build.mk

$(OUTELF): $(ALLOBJS) $(LINKER_SCRIPT)

    @echo linking $@

    $(NOECHO)$(LD) $(LDFLAGS) -T $(LINKER_SCRIPT) $(ALLOBJS) $(LIBGCC) -o $@

 

bootable/bootloader/lk/makefile:33:OUTBIN := $(BUILDDIR)/lk.bin

bootable/bootloader/lk/makefile:34:OUTELF := $(BUILDDIR)/lk

 

 

./lk/platform/msm7x30/rules.mk:23:LINKER_SCRIPT += $(BUILDDIR)/system-onesegment.ld

 

 

==》連接 lk

linking ../../.././out/target/product/msm7630_surf/obj/nandwrite/build-msm7630_surf_nandwrite/lk

linking ../../.././out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk

generating image: ../../.././out/target/product/msm7630_surf/obj/nandwrite/build-msm7630_surf_nandwrite/lk.bin

generating image: ../../.././out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk.bin

   text    data     bss     dec     hex filename

  29592    7388   42720   79700   13754 ../../.././out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk

   text    data     bss     dec     hex filename

  25780     184   34000   59964    ea3c ../../.././out/target/product/msm7630_surf/obj/nandwrite/build-msm7630_surf_nandwrite/lk

 

==》以 binary 格式,把文件 out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk 輸出到:

out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk.bin

arm-eabi-objcopy -O binary out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk.bin

 

==》

生成... out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk.lst

生成... out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk.debug.lst

生成... out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk.sym

生成... out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk.size

make[1]:正在離開目錄  /opt/workspace/gphone/qualcomm/eclair-M7630AABBQMLZA1150/bootable/bootloader/lk

==》

make -C kernel O=../out/target/product/msm7630_surf/obj/KERNEL_OBJ ARCH=arm CROSS_COMPILE=arm-eabi- msm7630-perf_defconfig

make[1]: 正在進入目錄 /opt/workspace/gphone/qualcomm/eclair-M7630AABBQMLZA1150/kernel

generating symbols: ../../.././out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk.sym

generating size map: ../../.././out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk.size

 

mkheader 從 lk.bin 生成 appsboothd.mbn 語法: mkheader <bin> <hdr>

而後把 appsboothd.mbn 和 lk.bin 合併爲文件 appsboot.mbn,刪除 appsboothd.mbn 文件

appsboothd.mbn 大小 40K

./bootable/bootloader/lk/target/msm7630_surf/tools/mkheader out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk.bin out/target/product/msm7630_surf/appsboothd.mbn

合併 out/target/product/msm7630_surf/appsboothd.mbn out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk.bin 爲:

out/target/product/msm7630_surf/appsboot.mbn

cat out/target/product/msm7630_surf/appsboothd.mbn out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk.bin > out/target/product/msm7630_surf/appsboot.mbn

刪除:out/target/product/msm7630_surf/appsboothd.mbn

==================================================

1.3.1.3 boot.img 生成過程解析,怎樣手動生成 boog.img

boot.img 包括兩個部分: kernel 和 ramdisk ,經過命令:

make  out/target/product/msm7630_surf/boot.img showcommands

會自動生成 kernel 和 ramdisk,而後把二者合併製做成燒寫的鏡像文件:boot.img

kernel 爲 out/target/product/$TARGET_PRODUCT/obj/KERNEL_OBJ/arch/arm/boot/zImage

或者 out/target/product/$TARGET_PRODUCT/kernel , kernel 是 zImage 的拷貝

編譯內核以前必須獲取一個默認的配置文件 .config ,此配置文件能夠生成,或者來自默認配置,高通中 msm7630_surf 的

默認配置文件名爲: msm7630-perf_defconfig 在文件:

vendor/qcom/msm7630_surf/AndroidBoard.mk:45 中經過:

KERNEL_DEFCONFIG := msm7630-perf_defconfig 進行了指定。

咱們能夠經過命令:

make -j3 ARCH=arm CROSS_COMPILE=arm-eabi- kernel showcommands

或者經過以下命令一步步完成:

1. 獲取默認的內核配置並生成.config 的命令以下:

   make -C kernel O=../out/target/product/msm7630_surf/obj/KERNEL_OBJ ARCH=arm CROSS_COMPILE=arm-eabi- msm7630-perf_defconfig

   -C kernel 告訴 make 進入 kernel 工做目錄,到其下面尋找 makefile 文件

   O  內核編譯的中間文件以及編譯結果等都存儲在該目錄下,此作法的好處是不會在kernel源代碼目錄下生成垃圾文件

   ARCH=arm 告訴系統到 ./kernel/arch/$ARCH/configs/ 目錄下找文件 msm7630-perf_defconfig,生成的.config 保存在:

   out/target/product/msm7630_surf/obj/KERNEL_OBJ/.config

2. 手動編譯內核

   make -C kernel O=../out/target/product/msm7630_surf/obj/KERNEL_OBJ/

3. 若是須要配置內核,使用下面的命令

  make kernelconfig

  他首先會進入 menuconfig 界面,用戶配置完成之後,會把修改後的配置文件$(KERNEL_OUT)/.config 更新爲默認的配置文件

cp out/target/product/msm7627_ffa/obj/KERNEL_OBJ/.config kernel/arch/arm/configs/msm7627-perf_defconfig

  kernel/arch/arm/configs/$(KERNEL_DEFCONFIG)

 

4. 手動生成 ramdisk 執行命令

  make  out/target/product/msm7630_surf/ramdisk.img showcommands

    會用到命令:

  out/host/linux-x86/bin/mkbootfs out/target/product/msm7630_surf/root | out/host/linux-x86/bin/minigzip > \

  out/target/product/msm7630_surf/ramdisk.img

5. 手動生成 boot.img 須要使用命令 mkbootimg ,語法以下:

   mkbootimg --kernel 內核 --ramdisk ramdisk鏡像 --cmdline 命令行 --base 基地址 --pagesize 大小 --output 輸出的boot.img

 ==========

KERNEL=out/target/product/$TARGET_PRODUCT/kernel

KERNEL=out/target/product/$TARGET_PRODUCT/obj/KERNEL_OBJ/arch/arm/boot/zImage

RAMDISK=out/target/product/$TARGET_PRODUCT/ramdisk.img

CMDLINE="console=ttyDCC0 androidboot.hardware=qcom"

BASE=0x00200000

PAGESIZE=4096

OUTPUT=out/target/product/$TARGET_PRODUCT/boot.img

out/host/linux-x86/bin/mkbootimg  --kernel $KERNEL --ramdisk $RAMDISK --cmdline "$CMDLINE"  --base $BASE --pagesize $PAGESIZE --output $OUTPUT

=========================================

 

 

編譯 bootloader (appsboot.mbn) ,nandwrite 生成過程解析

./vendor/qcom/msm7630_surf/AndroidBoard.mk:25:

include bootable/bootloader/lk/AndroidBoot.mk

===================

由於有:

bootable/bootloader/lk/AndroidBoot.mk:3:

TARGET_BOOTLOADER := $(PRODUCT_OUT)/appsboot.mbn

INSTALLED_BOOTLOADER_TARGET := $(PRODUCT_OUT)/bootloader

file := $(INSTALLED_BOOTLOADER_TARGET)

ALL_PREBUILT += $(file)

$(file): $(TARGET_BOOTLOADER) | $(ACP)

        $(transform-prebuilt-to-target)

因此拷貝:

out/target/product/msm7630_surf/appsboot.mbn

爲:

out/target/product/msm7630_surf/bootloader

====================

由於有:

./bootable/bootloader/lk/AndroidBoot.mk:38:

TARGET_NANDWRITE := $(PRODUCT_OUT)/obj/nandwrite/build-$(TARGET_PRODUCT)_nandwrite/lk

# Copy nandwrite utility to target out directory

INSTALLED_NANDWRITE_TARGET := $(PRODUCT_OUT)/nandwrite

file := $(INSTALLED_NANDWRITE_TARGET)

ALL_PREBUILT += $(file)

$(file) : $(TARGET_NANDWRITE) | $(ACP)

        $(transform-prebuilt-to-target)

endif

因此拷貝:

out/target/product/msm7630_surf/obj/nandwrite/build-msm7630_surf_nandwrite/lk

爲:

out/target/product/msm7630_surf/nandwrite

=====================

編譯內核:

#----------------------------------------------------------------------

# Compile Linux Kernel

#----------------------------------------------------------------------

ifeq ($(KERNEL_DEFCONFIG),)

    KERNEL_DEFCONFIG := msm7630-perf_defconfig

endif

include kernel/AndroidKernel.mk

======================

 

編譯 appsboot.mbn

源代碼位於: bootable/bootloader/lk/

由於:

vendor/qcom/msm7630_surf/BoardConfig.mk:60:

TARGET_USERIMAGES_USE_EXT2 := true

因此:分別編譯支持nand 和 emmc啓動的 appsboot.mbn

===================

bootable/bootloader/lk/AndroidBoot.mk

$(TARGET_BOOTLOADER): appsbootldr_clean emmc_appsbootldr_clean $(BOOTLOADER_OUT) $(BOOTLOADER_EMMC_OUT)

        $(MAKE) -C bootable/bootloader/lk BOOTLOADER_OUT=../../../$(BOOTLOADER_OUT) $(TARGET_PRODUCT)

        $(MAKE) -C bootable/bootloader/lk BOOTLOADER_OUT=../../../$(BOOTLOADER_EMMC_OUT) $(TARGET_PRODUCT) EMMC_BOOT=1

 

$(TARGET_NANDWRITE): nandwrite_clean $(NANDWRITE_OUT)

        @echo $(TARGET_PRODUCT)_nandwrite

        $(MAKE) -C bootable/bootloader/lk BOOTLOADER_OUT=../../../$(NANDWRITE_OUT) $(TARGET_PRODUCT)_nandwrite BUILD_NANDWRITE=1

====================

-C 代表到目錄 bootable/bootloader/lk 下找 makfile 文件

bootable/bootloader/lk/makefile

====================

bootable/bootloader/lk/makefile:87:

include target/$(TARGET)/tools/makefile

bootable/bootloader/lk/target/msm7630_surf/tools/makefile

====================

appsboot.mbn: appsboothd.mbn $(OUTBIN)

        cat $(APPSBOOTHEADER_DIR)/appsboothd.mbn $(OUTBIN) > $(APPSBOOTHEADER_DIR)/appsboot.mbn

        rm -f $(APPSBOOTHEADER_DIR)/appsboothd.mbn

 

appsboothd.mbn: mkheader $(OUTBIN)

        $(SRC_DIR)/mkheader $(OUTBIN) $(APPSBOOTHEADER_DIR)/appsboothd.mbn

 

========================================

hexdump out/target/product/msm7630_surf/appsboothd.mbn

40個字節的內容以下:

-----

0000000 0005 0000 0002 0000 0000 0000 0000 0000

0000010 9074 0000 9074 0000 9074 0000 0000 0000

0000020 9074 0000 0000 0000                   

0000028

-----

咱們編譯的:

0000000 0005 0000 0002 0000 0000 0000 0000 0000

0000010 9074 0000 9074 0000 9074 0000 0000 0000

0000020 9074 0000 0000 0000

高通的:

0000000 0005 0000 0002 0000 0000 0000 0000 0010

0000010 99ac 0000 99ac 0000 99ac 0010 0000 0000

0000020 99ac 0010 0000 0000

 

 

 

We found that the contents of the first 40 bytes is not the same

 

hexdump  out/target/product/msm7630_surf/appsboot.mbn > bbk.txt

hexdump  ~/appsboot.mbn > qualcomm > qualcomm.txt   (appsboot.mbn from Qualcomm, can properly programmed system.img)

 

the first 40 bytes below:

Content from the compilation:

0000000 0005 0000 0002 0000 0000 0000 0000 0000

0000010 9074 0000 9074 0000 9074 0000 0000 0000

0000020 9074 0000 0000 0000

Content from the Qualcomm:

0000000 0005 0000 0002 0000 0000 0000 0000 0010

0000010 99ac 0000 99ac 0000 99ac 0010 0000 0000

0000020 99ac 0010 0000 0000

========

Analysis of the generation of appsboot.mbn,from the command:

cat out/target/product/msm7630_surf/appsboothd.mbn out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk.bin > out/target/product/msm7630_surf/appsboot.mbn

we known ,appsboot.mbn consists of two parts: appsboothd.mbn and lk.bin;

appsboothd.mbn come form command:

./bootable/bootloader/lk/target/msm7630_surf/tools/mkheader out/target/product/msm7630_surf/obj/BOOTLOADER_OBJ/build-msm7630_surf/lk.bin out/target/product/msm7630_surf/appsboothd.mbn

 

1.3.1.4 編譯過程存在的問題

1.3.1.4.1 prelinkmap 的時候 base 0xaff00000 out of range

build/tools/apriori/prelinkmap.c(100): build/core/prelink-linux-arm.map:13 base 0xaff00000 out of range.

./build/tools/apriori/prelinkmap.c:99:                  

"%s:%d base 0x%08x out of range.\n",

1.3.1.4.2 LOCAL_SDK_VERSION 使應用程序不能訪問hide的api

LOCAL_SDK_VERSION 會使應用程序不能訪問hide的api,若是要訪問自定義的api,那麼在個應用的Android.mk 文件中屏蔽掉 LOCAL_SDK_VERSION := current

./packages/apps/Mms/Android.mk:13:#LOCAL_SDK_VERSION := current

./packages/apps/BBKMms/Android.mk:13:#LOCAL_SDK_VERSION := current

./packages/apps/Camera/Android.mk:9:# LOCAL_SDK_VERSION := current

 

1.3.1.4.3 armv5te-vfp 編譯配置,致使一些遊戲運行不了

device/qcom/msm7627_ffa/BoardConfig.mk:56:

TARGET_ARCH_VARIANT := armv5te-vfp

 

build/core/combo/TARGET_linux-arm.mk:37:

TARGET_ARCH_SPECIFIC_MAKEFILE := $(BUILD_COMBOS)/arch/$(TARGET_ARCH)/$(TARGET_ARCH_VARIANT).mk

......

$(TARGET_ARCH_SPECIFIC_MAKEFILE)

 

 

build/core/combo/arch/arm/armv5te-vfp.mk:6:

include $(BUILD_COMBOS)/arch/arm/armv5te.mk

 

 

                    

build/core/combo/TARGET_linux-arm.mk:209:   

若是 WITH_JIT 沒有賦值,那麼在文件 TARGET_linux-arm.mk 中會設置 WITH_JIT 默認值爲 true

# Enable the Dalvik JIT compiler if not already specified.

ifeq ($(strip $(WITH_JIT)),)

    WITH_JIT := true

Endif

 

 

dalvik/vm/Android.mk

 

 

 

 

 

 

 

 

 

 

 

1.3.2 分佈式編譯 android 代碼

編譯服務安裝過程

1. unzip distcc.zip

2. cd distcc

3. chmod u+x installdistcc3.0.sh

4. sudo ./installdistcc3.0.sh

編譯過程

5. cp setenv-dp.sh path to android source code root

6. . ./setenv-dp.sh

7. make -j24

 

1.3.3 modem 代碼編譯流程分析

從 svn 下載 modem 源代碼,進入其根目錄

svn co http://172.20.127.15/repositories/TD1014/trunk/modem-M76XXTSNCJNLYM6050/

首先執行環境變量設置腳本

cd modem-M76XXTSNCJNLYM6050

. ./setenv-qualcomm.sh

編譯程序執行腳本

. ./make-TFNCKNLYM.sh

 

#!/bin/bash

echo ". ./AMSS/products/76XX//build/ms/bbkTFNCKNLYM.cmd $1"

. ./AMSS/products/76XX//build/ms/bbkTFNCKNLYM.cmd  $1

 

AMSS/products/76XX/build/ms/bbkTFNCKNLYM.cmd

cd ./AMSS/products/76XX//build/ms

. ./TFNCKNLYM.cmd $1

cd –

 

./AMSS/products/7x30//build/ms/AAABQOLYM.cmd

AMSS/products/76XX/build/ms/TFNCKNLYM.cmd

make -r -f dmss76XXmodem.mak BUILD_UNIX=yes IMAGE=MODEM_PROC USES_SEC_CLNT=yes USES_MDDI=yes USES_CRYPTOMINCS=yes USES_RUIM=yes USES_PDCP=yes USES_HAL=yes USES_HSU_CHG_BOOT=yes USES_PMEM_REMOTE=yes USES_SDCC=yes USES_SUPPORT_UMTS_GPS_PROTOCOLS=yes USES_CDMA=yes USES_HSU_FAST_CHARGE=yes USES_CHARGER=yes USES_HSU_OTG=yes USES_ERR_SERVICES=yes USES_UMTS=yes USES_FTM_BT_MODEM_DUALPROC=yes USES_SMD_PORT_MGR=yes USES_SPLIT_CODE_DATA=yes USES_EXPORT_7K_APIS=yes USES_EBI1_TURBO_FFA=yes USES_SEC=yes USES_HDR=yes USES_DDR32_CFG_DATA=yes USES_HSU=yes USES_ONCRPC=yes USES_PHLP_XCVR=yes USES_SFS=yes USES_EFS2=yes USES_STRIP_NO_ODM=yes USES_SMD=yes USES_FEATURE_CGPS_XTRA=yes USES_VOCRTCV=yes USES_HS_USB_CHG_REMOTE_API=yes USES_CGPS=yes USES_FLASH_DAL=yes USES_ARM_ASM_SPINLOCK=yes USES_REL_C=yes USES_OEM_RAPI=yes USES_FEATURE_CGPS_XTRA_T=yes USES_IGUANA=yes USES_DAL=yes USES_LINUX_BT=yes USES_IPHC=yes USES_SEC_SVC=yes USES_ONCRPC_PROXY=yes USES_ONCRPC_ROUTER=yes USES_ONCRPC_CB=yes USES_NO_DEBUG=yes USES_DOG_KEEPALIVE=yes USES_HW7500=yes USES_VOCVP3=yes USES_VGA_CONTENT=yes USES_CGPS_SEC=yes USES_AUTH=yes USES_SMEM=yes USES_PICT_BRIDGE=yes USES_QOS=yes USES_BUS_MON_AXI_BUS_HANG_FIXED=yes USES_L4=yes USES_SBI=yes USES_HSU_MS_FD=yes USES_UIM=yes USES_IMG_UPDATE=yes USES_I2C_ON_APPS=yes USES_RPC_ROUTER_XAL_SMD=yes USES_CDMA2000=yes USES_SMEM_LOG=yes USES_EXPORT_MCCMEID=yes USES_NAND8_2K_CFG_DATA=yes USES_BUILD_NATIVELINUX_MODEM=yes USES_GSTK=yes USES_PS_DUN=yes USES_DEM=yes USES_DDR_ONLY=yes USES_DMOV=yes USES_HSU_ECM=yes USES_SUPPORT_CDMA_GPS_PROTOCOLS=yes USES_MBCBASBA=yes USES_BUS_PERF=yes USES_HIGH_POWER_CLK_FREQUENCY_PLAN=yes USES_GZRF6500=yes ASIC=76XXT BUILD=TFNCKNLYM VERSION=6050 BUILDDIR=TFNCKNLYM $1

 

1.3.3.1 單獨編譯某個模塊(如:qcsbl oemsbl)

編譯 modem   的主 makefile 文件爲 AMSS/products/76XX/build/ms/dmss76XXmodem.mak

. ./make-TFNCKNLYM.sh genqcsbl  單獨生成

. ./make-TFNCKNLYM.sh genoemsbl

 

./AMSS/products/76XX/build/ms/boot_targets_sec.min:1200

genqcsbl: $(MBNPATH_QCSBL)/qcsbl.mbn $(CERTDIR_QCSBL)/exist

./AMSS/products/76XX/build/ms/boot_targets_nonsec.min:870:

genqcsbl: $(MBNPATH)/qcsbl.mbn

./AMSS/products/76XX/build/ms/dmss76XXmodem.mak:49:

ifeq ($(USES_SECBOOT),yes)

   SEC_MODE = sec

else

   SEC_MODE = nonsec

endif

include boot_targets_$(SEC_MODE).min

./AMSS/products/76XX/build/ms/boot_targets_sec.min:108:

SECBOOT=$(SRCROOT)/secboot

./AMSS/products/76XX/build/ms/boot_targets_nonsec.min:107:

SECBOOT=$(SRCROOT)/secboot

 

./AMSS/products/76XX/build/ms/boot_targets_nonsec.min:872:

genoemsbl: $(MBNPATH)/oemsbl.mbn $(OEMSBL_HD_FILE_NAME)

./AMSS/products/76XX/build/ms/bin/TFNCKNLY/oemsbl.mbn

./AMSS/products/76XX/build/ms/bin/TFNCKNLY/oemsblhd.mbn

 

 

AMSS/products/76XX/build/ms/dmss76XXmodem.mak

...

all : dmss

...

include dmss_flags.min

include dmss_76XXT_flags.min

include incpaths.min

include armtools.min

-include amss_lint_flags.min

include dmss_objects.min

include boot_targets_$(SEC_MODE).min

...

include dmss_rules.min

-include amss_lint_rules.min

...

corebsp_build : corebsp_build_action corebsp_create_incpaths corebsp_setup

 

.PHONY: corebsp_build_action

corebsp_build_action :

ifeq ($(USES_COREBSP_BUILD_SYSTEM), yes)

    $(warning COREBSP Build System Enabled)

    @echo ================= COREBSP Build =======================================

    @echo COREBSP Build System and AMSS Objects

    #$(MAKE) -f $(COREBSP_BUILD)/msm7x30_modem.mak $(MAKEFLAGS)

 

    $(MAKE) -f $(COREBSP_BUILD)/msm7x30_modem.mak

    #$(MAKE) -f $(COREBSP_BUILD)/msm7x30_modem.mak -rk

    @echo COREBSP AMSS Libraries

   @if test -f $(COREBSP_BUILD)/msm7x30_lib.mak; then $(MAKE) -f $(COREBSP_BUILD)/msm7x30_lib.mak corebsplibs ; fi

    @echo ================= COREBSP Build Done ==================================

else

    $(warning COREBSP Build System Disabled)

    include $(COREBSP_BUILD)/dmss_objects.min

    OBJECTS := $(OBJECTS) $(COREBSP_OBJECTS)

    QCTLIBS := $(QCTLIBS) $(COREBSP_QCTLIBS)

Endif

...

編譯規則從 all : dmss 開始

dmss 規則 在文件 ./AMSS/products/7x30/build/ms/dmss_rules.min 中

...

ifeq ($(USES_L4), yes)

    ifeq ($(IMAGE), APPS_PROC)

        ifeq ($(USES_BUILD_NATIVELINUX_APPS), yes)

        #dmss : $(TARGETDIR)/exist setup firmware prereqs deps corebsp_build libs copybar exe bldprod

        dmss : $(TARGETDIR)/exist prereqs exe bldprod

    else

        #dmss : $(TARGETDIR)/exist setup firmware prereqs deps corebsp_build libs copybar exe bldprod

        dmss : $(TARGETDIR)/exist setup prereqs exe bldprod

    endif

    else

    ifneq ($(USES_OBJECT_ONLY), yes)

        ifeq ($(USES_SDCC_BOOT), yes)

            dmss : $(TARGETDIR)/exist setup firmware prereqs deps corebsp_build libs copybar exe bldprod create_mem_feat_html partition

        else

            dmss : $(TARGETDIR)/exist setup firmware prereqs deps corebsp_build libs copybar exe bldprod create_mem_feat_html

        endif

    else

        ifeq ($(USES_SDCC_BOOT), yes)

        dmss : $(TARGETDIR)/exist setup deps corebsp_build libs copybar exe bldprod create_mem_feat_html partition

        else

            dmss : $(TARGETDIR)/exist setup deps corebsp_build libs copybar exe bldprod create_mem_feat_html

        endif

    endif

    endif

endif

...

.PHONY: setup

setup : corebsp_create_incpaths create_incpaths amsssetup amsslinkaddress firmware

...

BUILDID 爲 AAABQOLYM 的腳本,比較關心的編譯選項有:

BUILD_UNIX=yes

USES_L4=yes

IMAGE=MODEM_PROC

USES_LPDDR2=yes

USES_SDCC=yes

USES_SDCC_BOOT=yes

因此 dmss 規則爲:

dmss : $(TARGETDIR)/exist setup deps corebsp_build libs copybar exe bldprod create_mem_feat_html partition

 

下面將分別對這些規則進行分析:

1.3.3.2 $(TARGETDIR)/exist 規則解析

1.3.3.3 setup規則解析

setup : corebsp_create_incpaths create_incpaths amsssetup amsslinkaddress firmware

1.3.3.3.1 corebsp_create_incpaths

1.3.3.3.2 create_incpaths

1.3.3.3.3 amsssetup

1.3.3.3.4 amsslinkaddress

amsslinkaddress 規則在文件:

./AMSS/products/7x30/build/ms/dmss_rules.min:871 中

amsslinkaddress : amsssetup

    @echo Generate AMSS Link Address file: $(CUSTL4SCLFILE).....

    @$(GEN_AMSS_LINK_ADDRESS)

amsssetup : create_incpaths

 

GEN_AMSS_LINK_ADDRESS 執行的是文件:

./AMSS/products/7x30/build/ms/dmss_rules.min:696 中的函數

。。。

L4_BASE_DIR := ../../core/kernel

AMSS_RELOC_DIR := build_$(BUILD_KCFG)/amss/bin

PLATMSDIR := ../../core/kernel/build_$(BUILD_KCFG)/ms

ELFWEAVER_CMD = python tools/pyelf/elfweaver

define GEN_AMSS_LINK_ADDRESS

    @echo --------------------------------------------------------

    @echo Determining AMSS link address from target XML file...

    @-if test -f $(CUSTL4SCLFILE); then rm $(CUSTL4SCLFILE); fi

    @echo "#ifndef CUST_L4_SCL_$(BUILD_KCFG)_H" >> $(CUSTL4SCLFILE)

    @echo "#define CUST_L4_SCL_$(BUILD_KCFG)_H" >> $(CUSTL4SCLFILE)

    @echo -n "#define SCL_L4_START_ADDRESS " >> $(CUSTL4SCLFILE)

    @echo Preprocessing XML file into quartz_cfg_$(BUILD)_cpp.xml...

 

    @echo Preprocessing XML file into quartz_cfg_machine_$(BUILD)_cpp.xml...

    $(CC) -E $(CFLAGS) $(DMSS_CFLAGS) $(ALL_INCLUDES) $(DIRNAME) -I"$(ARMINC)" $(BUILD_VERSION) $(APPFLAGS) $(MSG_BT_SSID) $(OBJ_CMD) quartz_cfg_machine_$(BUILD)_cpp.xml quartz_cfg_machine.xml

    @echo Copying cleaned XML file to quartz_cfg_machine_$(BUILD).xml...

    ./cleanup_xml.pl -i quartz_cfg_machine_$(BUILD)_cpp.xml -o quartz_cfg_machine_$(BUILD).xml

    rm -f quartz_cfg_machine_$(BUILD)_cpp.xml

 

    @echo Preprocessing XML file into quartz_cfg_$(BUILD)_cpp.xml...

    $(CC) -E $(CFLAGS) -DAMSS_RELOC_LC=\"$(AMSS_RELOC_DIR)/$(BUILD_LC).reloc\" -DQUARTZ_MACHINE_XML=\"../../build/ms/quartz_cfg_machine_$(BUILD).xml\" $(DMSS_CFLAGS) $(COREBSP_XALL_INCLUDES) $(ALL_INCLUDES) $(DIRNAME) -I"$(ARMINC)" -I"../../core/systemdrivers/hwio/chipset/msm7x30/inc/plat/l4" $(BUILD_VERSION) $(APPFLAGS) $(MSG_BT_SSID) $(OBJ_CMD) quartz_cfg_$(BUILD)_cpp.xml quartz_cfg.xml

    @echo Copying cleaned XML file to quartz_cfg_$(BUILD).xml...

    ./cleanup_xml.pl -i quartz_cfg_$(BUILD)_cpp.xml -o quartz_cfg_$(BUILD).xml

    rm -f quartz_cfg_$(BUILD)_cpp.xml

 

    @echo Determining AMSS link address...

    @cd $(L4_BASE_DIR); $(ELFWEAVER_CMD) merge ../../build/ms/quartz_cfg_$(BUILD).xml --ignore="AMSS" --lastphys="physical" >> ../../build/ms/$(CUSTL4SCLFILE)

    @echo "#endif" >> $(CUSTL4SCLFILE)

    @echo Done.

    @echo ------------------------------------------------------------------

。。。

 

@echo Generate AMSS Link Address file: $(CUSTL4SCLFILE).....

中的 CUSTL4SCLFILE 爲: cust_l4_scl_M.h

@echo "#ifndef CUST_L4_SCL_$(BUILD_KCFG)_H" >> $(CUSTL4SCLFILE)

@echo "#define CUST_L4_SCL_$(BUILD_KCFG)_H" >> $(CUSTL4SCLFILE)

@echo -n "#define SCL_L4_START_ADDRESS " >> $(CUSTL4SCLFILE)

@echo "#endif" >> $(CUSTL4SCLFILE)

輸出文件 ./AMSS/products/7x30/build/ms/cust_l4_scl_M.h ,內容爲:

#ifndef CUST_L4_SCL_M_H

#define CUST_L4_SCL_M_H

#define SCL_L4_START_ADDRESS 0x4864000

#endif

 

 

/home/gphone/ARM//RVCT/Programs/2.2/593/linux-pentium/tcc -E -c --cpu ARM1136J-S --apcs /noswst/interwork --littleend --force_new_nothrow -Otime -O1 -O1 -DT_ARM -D__ARMEL__ -DCUST_H="custaabbqolym.h" -D__MSMHW_APPS_PROC__=2 -D__MSMHW_MODEM_PROC__=1 -D__MSMHW_PROC_DEF__=__MSMHW_MODEM_PROC__ -DMSMHW_MODEM_PROC -DIMAGE_MODEM_PROC -DASSERT=ASSERT_FATAL -I../../core/api/systemdrivers/hwio/msm7x30/inc -I../../core/api/systemdrivers/hwio/msm7x30/inc/plat/l4/user -I../../core/api/systemdrivers/hwio/msm7x30/inc/proc/modem -I../../apps/nonpkbrew/pk/inc/msm -I../../apps/nonpkbrew/pk/inc -I../../apps/nonpkbrew/pk/src -I../../apps/nonpkbrew/pk/src/msm -I../../apps/nonpkbrew/pk/../sdk/inc -I../../apps/brew/sdk/inc -I../../apps/brew/inc -I../../apps/brew/pk/inc/msm -I../../apps/brew/pk/inc -I../../apps/brew/pk/src -I../../apps/brew/src/OEM -I../../apps/brew/pk/src/msm -I../../apps/brew/inc/OEM -I../../apps/brew/src/OEM/msm -I../../apps/brew/src/OEM/OEMNotify/inc -I../../apps/brew/src/OEM/OEMConfigItem/inc -I../../apps/brew/src/OEM/OEMSound -I../../apps/brew/src/OEM/OEMSysClock/msm -I../../apps/brew/src/OEM/OEMShellBeep -I../../apps/brew/src/OEM/OEMServingNetworks/msm -I../../apps/brew/src/OEM/OEMAnnunciatorControl -I../../multimedia/adsp_diag -I../../apps/staticextensions/inc -I../../apps/staticextensions/oem/inc -I../../apps/staticextensions/oem/src -I../../wconnect/bthost/soccfg/inc -I../../wconnect/bthost/ftm/inc -I../../modem/uim/gstk/inc -I../../modem/uim/gstk/src -I../../modem/uim/estk/inc -I../../modem/uim/estk/src -I../../apps/DynamicExtensions/IMediaVideo -I../../modem/uim/dctstk/src -I../../core/api/hwengines -I../../multimedia/api/adsprtossvc -I../../core/securemsm/ipsec/inc -I../../core/securemsm/ipsec/src -I../../core/securemsm/akaalgo/inc -I../../core/securemsm/akaalgo/src -I../../wconnect/api/rapi/wlanhs/inc -I../../wconnect/api/wlanhs --via ../../build/ms/corebsp.inc --via ../../build/ms/M7X30AABBQOLYM/M7X30AABBQOLYM.inc -I../../modem/qchat/inc -I ../../modem/wms/src/CMCNas/inc -I/home/gphone/ARM//RVCT/Data/2.2/349/include/unix -DBUILD_ASIC="7X30A" -DBUILD_TARGET="AABBQOLYM" -DBUILD_VER="1250" -o quartz_cfg_machine_AABBQOLYM_cpp.xml quartz_cfg_machine.xml

 

PLATMSDIR := ../../core/kernel/build_$(BUILD_KCFG)/ms

拷貝文件

./AMSS/products/7x30/build/ms/loadsyms_M.cmm

./AMSS/products/7x30/build/ms/loadsyms_M.men

./AMSS/products/7x30/build/ms/quartz_constants_M.cmm

 

./AMSS/products/7x30/core/kernel/build_M/ms/

 

 

------------------------------------------------------------------

Generate AMSS Link Address file: cust_l4_scl_M.h.....

------------------------------------------------------------------

Determining AMSS link address from target XML file...

Preprocessing XML file into quartz_cfg_AABBQOLYM_cpp.xml...

Preprocessing XML file into quartz_cfg_machine_AABBQOLYM_cpp.xml...

Copying cleaned XML file to quartz_cfg_machine_AABBQOLYM.xml...

Preprocessing XML file into quartz_cfg_AABBQOLYM_cpp.xml...

Copying cleaned XML file to quartz_cfg_AABBQOLYM.xml...

Determining AMSS link address...

Done.

 

1.3.3.3.5 firmware

1.3.3.4 deps規則解析

1.3.3.5 corebsp_build規則解析

corebsp_build : corebsp_build_action corebsp_create_incpaths corebsp_setup

corebsp_build 規則包括三個過程:

corebsp_build_action

corebsp_create_incpaths

corebsp_setup

經過命令 . ./make-AAABQOLYM.sh corebsp_build 能夠單獨對 corebsp_build 部分進行編譯。

 

1.3.3.5.1 corebsp_build_action

corebsp_build_action :

ifeq ($(USES_COREBSP_BUILD_SYSTEM), yes)

    $(warning COREBSP Build System Enabled)

    @echo ================= COREBSP Build ====================================

    @echo COREBSP Build System and AMSS Objects

    #$(MAKE) -f $(COREBSP_BUILD)/msm7x30_modem.mak $(MAKEFLAGS)

 

    $(MAKE) -f $(COREBSP_BUILD)/msm7x30_modem.mak

    #$(MAKE) -f $(COREBSP_BUILD)/msm7x30_modem.mak -rk

    @echo COREBSP AMSS Libraries

   @if test -f $(COREBSP_BUILD)/msm7x30_lib.mak; then $(MAKE) -f $(COREBSP_BUILD)/msm7x30_lib.mak corebsplibs ; fi

    @echo ================= COREBSP Build Done ================================

else

    $(warning COREBSP Build System Disabled)

    include $(COREBSP_BUILD)/dmss_objects.min

    OBJECTS := $(OBJECTS) $(COREBSP_OBJECTS)

    QCTLIBS := $(QCTLIBS) $(COREBSP_QCTLIBS)

endif

由於:

USES_COREBSP_BUILD_SYSTEM=yes

$(COREBSP_BUILD)/msm7x30_lib.mak  文件不存在

因此 corebsp_build_action  規則

執行語句:$(MAKE) -f $(COREBSP_BUILD)/msm7x30_modem.mak

...

all : corebsp_scons corebsp

 

1.3.3.5.1.1 corebsp_scons 規則

./AMSS/products/7x30/core/bsp/build/dmss_rules.min 中。

 

corebsp_scons 包括三個部分:

corebsp_scons_start  顯示信息  @echo Building CoreBSP 建立目錄 mkdir -p $(COREBSP_BUILD)/data

corebsp_scons_action 主體部分

corebsp_scons_done   顯示信息  @echo Completed CoreBSP

 

1.3.3.5.1.1.1 corebsp_scons_start

2.3.3.5.1.1.1 corebsp_scons_action

corebsp_scons_action 規則在文件 ./AMSS/products/7x30/core/bsp/build/dmss_rules.min:263 中,它完成核心bsp的編譯。

./AMSS/products/7x30/core/bsp/tools/emmcbld/build/emmcbld.mbn

./AMSS/products/7x30/core/bsp/tools/flash/ehostdl/build/enandprg_AABBQOLYM.mbn

./AMSS/products/7x30/build/ms/bin/AABBQOLY/adsp.mbn

./AMSS/products/7x30/core/bsp/amsslibs/build/qdsp5/AMSS_AABBQOLYM.mbn

./AMSS/products/7x30/core/bsp/tools/flash/hostdl/build/nandprg_AABBQOLYM.mbn

./AMSS/products/7x30/build/ms/bin/AABBQOLY/partition.mbn

./AMSS/products/7x30/core/bsp/bootloaders/partition/build/partition_AABBQOLYM.mbn

./AMSS/products/7x30/build/ms/bin/AABBQOLY/osbl.mbn

./AMSS/products/7x30/core/bsp/bootloaders/osbl/build/osbl_AABBQOLYM.mbn

./AMSS/products/7x30/build/ms/bin/AABBQOLY/fsbl.mbn

./AMSS/products/7x30/core/bsp/bootloaders/fsbl/build/fsbl_AABBQOLYM.mbn

./AMSS/products/7x30/build/ms/bin/AABBQOLY/dbl.mbn

./AMSS/products/7x30/core/bsp/bootloaders/dbl/build/dbl_AABBQOLYM_preamble.mbn

./AMSS/products/7x30/core/bsp/bootloaders/dbl/build/dbl_AABBQOLYM.mbn

以上各部分都是在此過程當中完成。

corebsp_scons_action : corebsp_genincpaths corebsp_genuses

    @echo -------------------------------------------------------------------

    $(scons_builder)

    @echo -------------------------------------------------------------------

 

corebsp_genincpaths :

產生基於 AMSS 的頭文件信息,經過下面命令完成。

perl $(COREBSP_BUILD)/scripts/genpaths.pl -min incpaths.min -buildid $(BUILD) -makeflags "$(MAKEFLAGS)" > $(COREBSP_BUILD)/data/incpaths$(BUILD_LC).py

$(COREBSP_BUILD)/scripts/genpaths.pl        

爲文件:

./AMSS/products/7x30/core/bsp/build/scripts/genpaths.pl

$(COREBSP_BUILD)/data/incpaths$(BUILD_LC).py

爲文件:

./AMSS/products/7x30/core/bsp/build/data/incpathsaaabqmazm.py

 

corebsp_genuses:

$(scons_builder)

$(scons_builder) 的調用在文件 ./AMSS/products/7x30/core/bsp/build/dmss_rules.min:180:中

 

 

define scons_builder

        -chmod +x $(COREBSP_BUILD)/../tools/SCons/scons

        cd $(COREBSP_BUILD); \

        ../tools/SCons/scons$(SCONS_EXT) $(PLATFORM) CHIPSET=$(CHIPSET) BUILD_ID=$(BUILDID) BUILD_VER=$(VERSION) \

                MSM_ID=$(BUILD_MSM_ID) HAL_PLATFORM=$(HAL_PLAT) BUILD_ASIC=$(BUILD_ASIC) TARGET_FAMILY=$(TARGET_FAMILY) \

                --verbose=$(VERBOSE) --frommake $(MAKE_FLAGS)

endef

 

COREBSP_BUILD 等於 ${SRCROOT}/core/bsp/build

./AMSS/products/7x30/core/bsp/tools/SCons/scons

因此 scons_builder 實際執行了如下命令:

chmod +x ./AMSS/products/7x30/core/bsp/tools/SCons/scons

cd ./AMSS/products/7x30/core/bsp/build

./AMSS/products/7x30/core/bsp/tools/SCons/scons modem CHIPSET=msm7x30 BUILD_ID=AAABQMAZ BUILD_VER=1220 MSM_ID=7x30 HAL_PLATFORM=7x30 BUILD_ASIC=7X30A TARGET_FAMILY=7630 --verbose=0 –frommake

 

 

1.3.3.5.1.1.2.1 命令 pboot_gen_elf image_header pboot_add_hash 解析

pboot_gen_elf image_header pboot_add_hash 是編譯過程當中用到的幾個工具

編譯過程當中經常使用的幾個工具

命令 ./AMSS/products/7x30/tools/headergen/pboot_gen_elf 用法:

pboot_gen_elf [-d] elf_file scl_file output_elf output_hash

或者:

pboot_gen_elf [-d] elf_file output_hash

-d           - debug 模式

elf_file     - 格式爲ELF的輸入文件,它由linker生成

scl_file     - input progressive boot scatter load file

output_elf   - output ELF file

output_hash  - output hash table

例如:

PBOOT_GEN_ELF=./AMSS/products/7x30/tools/headergen/pboot_gen_elf

elf_file=./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/CORELIBS_AABBQMAZM.pbn

output_hash=./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/CORELIBS_AABBQMAZM.hash

$PBOOT_GEN_ELF  $elf_file $output_hash

 

命令 ./AMSS/products/7x30/tools/headergen/image_header  用法:

image_header flash_type header_type input_code_file output_header_file secure_type [dbl_preamble_file or elf_src_file]

flash_type         -  flash 類型:nand 或者 nor

header_type        -  頭類型能夠爲: dbl, dbl_preamble, osbl, appsbl, apps, amsshash, hostdl, ehostdl, dsp1hash, dsp2hash

input_code_file    - 用於生成文件頭的輸入文件

output_header_file - 生成的文件頭

secure_type        -  'secure' or 'nonsecure'

dbl_preamble_file  - 當 header_type 等於 'dbl_preamble' 的時候指向 dbl preamble 文件的路徑

elf_src_file       - 當 header_type 等於 'hash' 的時候指向 elf file corresponding to hash table 的路徑

例如:

=============

IMAGE_HEADER=./AMSS/products/7x30/tools/headergen/image_header

flash_type=nand

header_type=amsshash

input_code_file=./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/CORELIBS_AABBQMAZM.hash

output_header_file=./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/CORELIBS_AABBQMAZM.hash.hd

secure_type=nonsecure

dbl_preamble_file=

elf_src_file=./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/CORELIBS_AABBQMAZM.pbn

$IMAGE_HEADER  $flash_type $header_type $input_code_file $output_header_file $secure_type $elf_src_file

 

命令 AMSS/products/7x30/tools/headergen/pboot_add_hash 用法:

把 hash 頭和 hash 表插入到 ELF文件做爲起始段 ,在物理內存中它實際在最後。

pboot_add_hash [-d] elf_file hash_table output_elf

-d            - debug 模式

elf_file      - the ELF file

hash_table    - hash table (signed or not)

output_elf    - final output

PBOOT_ADD_HASH=./AMSS/products/7x30/tools/headergen/pboot_add_hash

elf_file=./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/CORELIBS_AABBQMAZM.pbn

hash_table=./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/CORELIBS_AABBQMAZM.hash_nonsec.mbn

output_elf=./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/CORELIBS_AABBQMAZM.mbn

$PBOOT_ADD_HASH  $elf_file  $hash_table  $output_elf

 

1.3.3.5.1.1.2.2env.BinBuilder 過程解析

 

1.3.3.5.1.1.2.3 env.MbnBuilder 過程解析

mbn 類型的文件是咱們最終燒寫到板子上的鏡像文件

在文件: ./AMSS/products/7x30/core/bsp/build/scripts/mbn_builder.py 中有 mbn 文件的編譯規則,要注意的是,不一樣的 modem 源代碼版本,它裏面的規則有可能不同。

1220 以及以前的版本,編譯規則中有:

def mbn_generate(env):

   #-------------------------------------------------------------------------

   # MBN builder definition

   #-------------------------------------------------------------------------

   mbn_act = env.GetBuilderAction(mbn_builder)

   mbn_bld = env.Builder(action = mbn_act,

                         emitter = mbn_emitter,

                         suffix = '.mbn')

 

   env.Append(BUILDERS = {'MbnBuilder' : mbn_bld})

  

   mbn_dummy_act = env.GetBuilderAction(mbn_dummy_file_gen)

   mbn_dummy_bld = env.Builder(action = mbn_dummy_act, suffix = '.mbn')

 

   env.Append(BUILDERS = {'MbnDummyBuilder' : mbn_dummy_bld})

 

1240 後的版本爲:

def mbn_generate(env):

   env.AddMethod(mbn_builder, "MbnBuilder")

   #-------------------------------------------------------------------------

   # MBN builder definition

   #-------------------------------------------------------------------------

   stage1_mbn_act = env.GetBuilderAction(stage1_mbn_builder)

   stage1_mbn_bld = env.Builder(action = stage1_mbn_act,

                         emitter = stage1_mbn_emitter,

                         suffix = '.mbn')

 

   env.Append(BUILDERS = {'Stage1MbnBuilder' : stage1_mbn_bld})

  

   stage2_mbn_act = env.GetBuilderAction(stage2_mbn_builder)

   stage2_mbn_bld = env.Builder(action = stage2_mbn_act,

                         emitter = stage2_mbn_emitter,

                         suffix = '.mbn')

 

   env.Append(BUILDERS = {'Stage2MbnBuilder' : stage2_mbn_bld})

  

   mbn_dummy_act = env.GetBuilderAction(mbn_dummy_file_gen)

   mbn_dummy_bld = env.Builder(action = mbn_dummy_act, suffix = '.mbn')

env.Append(BUILDERS = {'MbnDummyBuilder' : mbn_dummy_bld})

 

MbnBuilder 方法,它對應的函數爲 mbn_builder, 該函數也在文件:./AMSS/products/7x30/core/bsp/build/scripts/mbn_builder.py 中:

def mbn_builder(target, source, env):

   ...

   source_base = os.path.splitext(str(source[0]))[0]

   target_base = os.path.splitext(str(target[0]))[0]

   source_full = str(source[0])

   target_full = str(target[0])

1.3.3.5.1.1.2.4 env.MbnDummyBuilder 過程解析

./AMSS/products/7x30/core/bsp/build/scripts/mbn_builder.py:160:  

。。。

mbn_dummy_act = env.GetBuilderAction(mbn_dummy_file_gen)

mbn_dummy_bld = env.Builder(action = mbn_dummy_act, suffix = '.mbn')

env.Append(BUILDERS = {'MbnDummyBuilder' : mbn_dummy_bld})

。。。

def mbn_dummy_file_gen(target, source, env):

   target_str = str(target[0])

   file = open (target_str, "w")

   file.write("\nDummy file created " + target_str + "\n")

   file.close()

   return None

 

# 生成 fsbl elf

FSBL_elf = env.Program('${TARGET_NAME}', FSBL_objs, LIBS=FSBL_libs, LIBPATH=libs_path)

FSBL_bin = env.BinBuilder('${TARGET_NAME}', FSBL_elf)

# Generate dummy fsbl mbn

FSBL_mbn = env.MbnDummyBuilder('${TARGET_NAME}', None)

install_target_mbn = env.InstallAs('${MBN_ROOT}/fsbl.mbn', FSBL_mbn)

 

1.3.3.5.1.1.2.5fsbl.mbn 生成過程解析

./AMSS/products/7x30/core/bsp/bootloaders/fsbl/build/SConscript:203:  

# 生成 fsbl elf

FSBL_elf = env.Program('${TARGET_NAME}', FSBL_objs, LIBS=FSBL_libs, LIBPATH=libs_path)  

# Generate fsbl bin

FSBL_bin = env.BinBuilder('${TARGET_NAME}', FSBL_elf)

# Generate fsbl mbn

#FSBL_mbn = env.MbnBuilder('${TARGET_NAME}', FSBL_bin,

#   IMAGE_TYPE="fsbl", FLASH_TYPE=env['FLASH_TYPE'])

# 生成 dummy fsbl mbn

FSBL_mbn = env.MbnDummyBuilder('${TARGET_NAME}', None)     

install_target_mbn = env.InstallAs('${MBN_ROOT}/fsbl.mbn', FSBL_mbn)

 

1.3.3.5.1.1.2.6 dbl.mbn 生成過程解析

./AMSS/products/7x30/core/bsp/bootloaders/dbl/build/SConscript:230:

DBL_elf = env.Program('${TARGET_NAME}',DBL_objs , LIBS=DBL_libs, LIBPATH=libs_path) 

   DBL_bin = env.BinBuilder('${TARGET_NAME}', DBL_elf)

   DBL_mbn = env.MbnBuilder(env.subst('${TARGET_NAME}'), DBL_bin, IMAGE_TYPE="dbl", FLASH_TYPE="nand")

1.3.3.5.1.1.2.7 AMSS_AABBQOLYM.mbn 生成過程解析

./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/SConscript:252:  

target_mbn = env.MbnBuilder('${TARGET_NAME}', target_pbn, IMAGE_TYPE="amss_mbn",

1.3.3.5.1.1.2.8 adsp.mbn 生成過程解析

 

生成 adsp.mbn 的 scons 腳本爲:

./AMSS/products/7x30/core/bsp/amsslibs/build/qdsp5/SConscript

   adsp_bin_path = env.subst("${BUILD_ROOT}/multimedia/adspinfo/adsp.bin")

   adsp_mbn_path = env.subst("${BUILD_ROOT}/core/bsp/amsslibs/build/qdsp5/adsp.mbn")

   install_temp_adsp_mbn = env.InstallAs(adsp_mbn_path, adsp_bin_path) 

   ADSP_mbn = env.MbnBuilder('${TARGET_NAME}', adsp_mbn_path, IMAGE_TYPE="qdsp5", FLASH_TYPE=env['TARGET_FLASH_TYPE'])     

   install_adsp_mbn = env.InstallAs('${MBN_ROOT}/adsp.mbn', ADSP_mbn)

 

首先安裝文件:

AMSS/products/7x30/multimedia/adspinfo/adsp.bin

到:

AMSS/products/7x30/core/bsp/amsslibs/build/qdsp5/adsp.mbn

此時的 adsp.mbn 僅僅是文件 adsp.bin 的拷貝。

而後調用 env.MbnBuilder 由文件 AMSS/products/7x30/core/bsp/amsslibs/build/qdsp5/adsp.mbn生成:./AMSS/products/7x30/core/bsp/amsslibs/build/qdsp5/AMSS_AABBQOLYM.mbn

AMSS_AABBQOLYM.mbn 是 adsp.mbn 加了40個字節的頭信息,最後安裝此 AMSS_AABBQOLYM.mbn 到

AMSS/products/7x30/build/ms/bin/AABBQOLY/adsp.mbn

其中 env.MbnBuilder 執行的是文件:

./AMSS/products/7x30/core/bsp/build/scripts/mbn_builder.py:299 中的函數:

def mbn_builder(target, source, env)

 

AMSS/products/7x30/tools/headergen/image_header nand adspq5 AMSS/products/7x30/core/bsp/amsslibs/build/qdsp5/adsp.mbn AMSS/products/7x30/core/bsp/amsslibs/build/qdsp5/AMSS_AABBQOLYM.hd nonsecure

 

flash_type: nand

header_type: adspq5

code_file_name: /home/shared/qualcommon/HY11-N1496-2_1.2.40/AMSS/products/7x30/core/bsp/amsslibs/build/qdsp5/adsp.mbn

output_file_name: /home/shared/qualcommon/HY11-N1496-2_1.2.40/AMSS/products/7x30/core/bsp/amsslibs/build/qdsp5/AMSS_AABBQOLYM.hd

secure_type: nonsecure

image_size = 0x614AB4, code_size= =0x614AB4

 

1.3.3.5.1.1.2.9osbl.mbn 生成過程解析

./AMSS/products/7x30/core/bsp/bootloaders/osbl/build/SConscript:246:  

OSBL_mbn = env.MbnBuilder('${TARGET_NAME}', OSBL_bin,

 

1.3.3.5.1.1.2.10enandprg_AABBQOLYM.mbn 生成過程解析

./AMSS/products/7x30/core/bsp/tools/flash/ehostdl/build/SConscript:389:

# Generate enandprg.elf

enandprg_elf = env.Program('${TARGET_NAME}', source=[], LIBS=libs, LIBPATH=libs_path)

env.Depends(enandprg_elf, target_scl)

Clean(enandprg_elf, env.subst('${TARGET_NAME}.map'))

Clean(enandprg_elf, env.subst('${TARGET_NAME}.sym'))

# 把生成的 elf 文件拷貝到相應位置

install_enandprg_elf = env.Install("${BUILD_ROOT}/core/storage/flash/tools/src/hostdl",enandprg_elf)

# Generate ehostdl bin

target_bin = env.BinBuilder('${TARGET_NAME}', enandprg_elf)

# 生成 ehostdl mbn

target_mbn = env.MbnBuilder('${TARGET_NAME}', target_bin, IMAGE_TYPE="ehostdl", FLASH_TYPE="nand")

1.3.3.5.1.1.2.11 nandprg_AABBQOLYM.mbn 生成過程解析

./AMSS/products/7x30/core/bsp/tools/flash/hostdl/build/SConscript:401:

# Generate nandprg.elf

nandprg_elf = env.Program('${TARGET_NAME}', source=[], LIBS=libs, LIBPATH=libs_path)

env.Depends(nandprg_elf, target_scl)

Clean(nandprg_elf, env.subst('${TARGET_NAME}.map'))

Clean(nandprg_elf, env.subst('${TARGET_NAME}.sym'))

# 把生成的 elf 文件拷貝到相應位置

install_nandprg_elf = env.Install("${BUILD_ROOT}/core/storage/flash/tools/src/hostdl", nandprg_elf)

# Generate hostdl bin

target_bin = env.BinBuilder('${TARGET_NAME}', nandprg_elf)

# Generate hostdl mbn

target_mbn = env.MbnBuilder('${TARGET_NAME}', target_bin,IMAGE_TYPE="hostdl", FLASH_TYPE="nand")

# Generate nandprg.hex

nprg_hex = env.NPRGHexBuilder('NPRG${MSM_ID}_${BUILD_ID}', target_mbn,HOSTDL_ADDR=CODE_HDR_ADDR)

install_nandprg_hex = env.InstallAs('${MBN_ROOT}/NPRG${MSM_ID}.hex', nprg_hex)

 

 

1.3.3.5.1.1.2.12 emmcbld.mbn 生成過程解析

生成 emmcbld.mbn 的 scons 腳本爲:

./AMSS/products/7x30/core/bsp/tools/emmcbld/build/SConscript:289:

libs = root_env['LIBS']

libs_path = env['LIBPATH']

# Source PATH

EMMCBLD_SRC = "${BUILD_ROOT}/core/storage/tools/emmcbld"

。。。

env.VariantDir('.', EMMCBLD_SRC, duplicate=0) 

env.Replace(TARGET_NAME = 'emmcbld')

env.Replace(TARGET_BLD_KCFG = 'M')

env.Replace(TARGET_IMAGE = 'MODEM_PROC')

# 生成 scatter load 文件

target_scl = env.SclBuilder('${TARGET_NAME}', '${BUILD_ROOT}/core/storage/tools/emmcbld/emmcbld_in.scl')

# 生成 emmcbld elf 文件

target_elf = env.Program('${TARGET_NAME}', emmcbld_obj, LIBS=libs, LIBPATH=libs_path)

env.Depends(target_elf, target_scl)

Clean(target_elf, env.subst('${TARGET_NAME}.map'))

Clean(target_elf, env.subst('${TARGET_NAME}.sym'))

# 生成 Generate emmcbld bin 文件

target_bin = env.BinBuilder('${TARGET_NAME}', target_elf)

# 生成 Generate emmcbld mbn 文件

target_mbn = env.MbnBuilder('${TARGET_NAME}', target_bin, IMAGE_TYPE="emmcbld", FLASH_TYPE="nand")

# 生成 emmcbld.hex 文件

mprg_hex = env.NPRGHexBuilder('MPRG${MSM_ID}', target_mbn, HOSTDL_ADDR=CODE_HDR_ADDR)

install_emmcbld_hex = env.InstallAs('${MBN_ROOT}/MPRG${MSM_ID}.hex', mprg_hex)

經過語句:

target_elf = env.Program('${TARGET_NAME}', emmcbld_obj, LIBS=libs, LIBPATH=libs_path) 編譯 emmcbld 相關代碼生成 ./AMSS/products/7x30/core/bsp/tools/emmcbld/build/emmcbld.elf        LIBS 爲程序須要引入的庫,庫的路徑爲 LIBPATH 例如:

若是程序引入了其它的庫,庫名爲libbar.a,庫的目錄爲/usr/local/lib:  

Program('hello',Glob("*.c"),LIBS='bar',LIBPATH='/usr/local/lib')

 

env.Depends(target_elf, target_scl)明確以來關係,代表生成 mmcbld.elf 須要 emmcbld.scl

 

Clean(target_elf, env.subst('${TARGET_NAME}.map'))

Clean(target_elf, env.subst('${TARGET_NAME}.sym'))

Clean 調用的是文件:

./AMSS/products/7x30/core/bsp/tools/SCons/Environment.py:1814:中的函數

def Clean(self, targets, files):

 

flash_type: nand

header_type: emmcbld

code_file_name: /home/shared/HY11-N1496-3_1.2.50/AMSS/products/7x30/core/bsp/tools/emmcbld/build/emmcbld.bin

output_file_name: /home/shared/HY11-N1496-3_1.2.50/AMSS/products/7x30/core/bsp/tools/emmcbld/build/emmcbld.hd

secure_type: nonsecure

image_size = 0x23E88, code_size= =0x23E88

=== Generating tool/emmcbld/MPRG7x30.hex

Install file: "/home/shared/HY11-N1496-3_1.2.50/AMSS/products/7x30/core/bsp/tools/emmcbld/build/MPRG7x30.hex" as "/home/shared/HY11-N1496-3_1.2.50/AMSS/products/7x30/build/ms/bin/AABBQOLY/MPRG7x30.hex"

 

3.3.3.5.1.1.1 corebsp_scons_done

1.3.3.5.1.2 corebsp

1.3.3.5.2 corebsp_create_incpaths

1.3.3.5.3 corebsp_setup

1.3.3.6 libs

.PHONY: setup

setup : corebsp_create_incpaths create_incpaths amsssetup amsslinkaddress firmware

...

#生成 Library

ifneq ($(USES_OBJECT_ONLY), yes)

libs : $(LIBDIR)/exist copybar firmware prereqs $(LIBRARIES)

    @if test -f dmss_lib.mak; then $(MAKE) --no-print-directory -f dmss_lib.mak; fi

else

libs : $(LIBDIR)/exist copybar $(LIBRARIES)

    @if test -f dmss_lib.mak; then $(MAKE) --no-print-directory -f dmss_lib.mak; fi

endif

...

ifeq ($(IMAGE), APPS_PROC)

$(TARGETDIR)/exist $(LIBDIR)/exist $(MBNPATH)/exist:

else

$(TARGETDIR)/exist $(LIBDIR)/exist:

endif

    @echo ---------------------------------------------------------------

    @echo Creating path for ${@D}

    @echo

    @if test ! -f $@ && test ! -d ${@D}; then mkdir -p ${@D}; mkdir -p ${@D}; fi

    @echo Building ${@D} > $@

    @echo ---------------------------------------------------------------

...

1.3.3.7 copybar規則解析

1.3.3.8 exe規則解析

1.3.3.8.1 CORELIBS_AABBQOLYM.mbn生成過程解析

1.3.3.8.2 amss.mbn 生成過程解析

   # Create PBN, MBN, etc..

   install_target_reloc = env.InstallAs(AMSS_RELOC, target_elf)

   # Build env pbn files

   target_pbn = env.PbnBuilder('${TARGET_NAME}', ["${BUILD_MS_ROOT}/quartz_cfg_${BUILD_ID}",install_target_reloc])

   install_target_pbn = env.InstallAs(BOOTING_PBN, target_pbn)

   # Build CMM scripts

   quartz_constant_cmm = env.QuartzConstBuilder('quartz_const_${TARGET_NAME}', ["${L4_ROOT}/build_${TARGET_BLD_KCFG}/ms/quartz_constants_${TARGET_BLD_KCFG}.cmm",install_target_pbn,"${BUILD_MS_ROOT}/quartz_cfg_${BUILD_ID}.xml",])

   # install scripts

   install_quartz_constant_cmm = env.InstallAs("${BUILD_MS_ROOT}/quartz_constants_${TARGET_BLD_KCFG}.cmm",quartz_constant_cmm)

   install_loadsyms_cmm = env.Install("${BUILD_MS_ROOT}","${L4_ROOT}/build_${TARGET_BLD_KCFG}/ms/loadsyms_${TARGET_BLD_KCFG}.cmm",)  

   install_loadsyms_men = env.Install("${BUILD_MS_ROOT}","${L4_ROOT}/build_${TARGET_BLD_KCFG}/ms/loadsyms_${TARGET_BLD_KCFG}.men",)

   install_cmm_scripts = [install_quartz_constant_cmm,install_loadsyms_cmm,install_loadsyms_men,]

   # Build env mbn files

   target_mbn = env.MbnBuilder('${TARGET_NAME}', target_pbn, IMAGE_TYPE="amss_mbn",FLASH_TYPE=env['TARGET_FLASH_TYPE'])

 

 

1.3.3.9 bldprod規則解析

1.3.3.10 create_mem_feat_html規則解析

此規則在 文件中

./AMSS/products/7x30/core/bsp/build/SConstruct:22:print "  

Loading CBSP build system"

./AMSS/products/7x30/core/bsp/coreimg/build/SConscript:24:  

print "   Loading CBSP Image build system"

./AMSS/products/7x30/core/bsp/tools/flash/build/SConstruct:31:

print "   Loading CBSP build system"

./AMSS/products/7x30/core/bsp/tools/boot/build/SConstruct:31:

print "   Loading CBSP build system"

./AMSS/products/7x30/core/bsp/bootloaders/build/SConstruct:31:

print "   Loading CBSP build system"

 

perl ./AMSS/products/7x30/build/ms/cleanup_xml.pl -i

 

./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/quartz_cfg_AAABQMAZM.xml

./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/quartz_cfg_machine_AAABQMAZM.xml

./AMSS/products/7x30/build/ms/quartz_cfg_AABBQMAZM.xml

./AMSS/products/7x30/build/ms/quartz_cfg_AABBQOLYM.xml

./AMSS/products/7x30/build/ms/quartz_cfg_AAABQMAZM.xml

./AMSS/products/7x30/build/ms/quartz_cfg_machine_AABBQOLYM.xml

./AMSS/products/7x30/build/ms/quartz_cfg_machine_AAABQMAZM.xml

./AMSS/products/7x30/build/ms/quartz_cfg_machine_AABBQMAZM.xml

./AMSS/products/7x30/build/ms/quartz_cfg_machine.xml

 

./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/CORELIBS_AAABQMAZM.mbn

./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/CORELIBS_AAABQMAZM.hash_nonsec.mbn

 

 

./AMSS/products/7x30/core/bsp/build/scripts/mbn_builder.py

      if env.subst("$IMAGE_TYPE") != "amss_mbn":

         target_bin_nonsec = os.path.join(target_bin_base, target_bin_dir, \

            str(os.path.split(target_base)[1]) + "_nonsec.mbn")

      else:

         target_bin_nonsec = os.path.join(target_bin_base, target_bin_dir, \

            str(os.path.split(target_base)[1]) + ".hash_nonsec.mbn")

 

 

 

 

    quartz_xml = env.QuartzXMLBuilder('quartz_cfg_${TARGET_NAME}',

         ['${BUILD_MS_ROOT}/quartz_cfg.xml', quartz_machine_xml],

      #-------------------------------------------------------------------------

      # Build env pbn files

      #-------------------------------------------------------------------------

      target_pbn = env.PbnBuilder(

         '${TARGET_NAME}', [quartz_xml, install_target_reloc])

 

      # Copy qcoreimg_M.pbn to platform\l4\build_M\bootimg.pbn for RUMI */

      install_target_pbn = env.InstallAs(

         '${L4_ROOT}/build_${TARGET_BLD_KCFG}/bootimg.pbn', target_pbn)

 

 

      target_mbn = env.MbnBuilder('${TARGET_NAME}', target_pbn, IMAGE_TYPE="amss_mbn",

         FLASH_TYPE=env['TARGET_FLASH_TYPE'])

 

      install_target_mbn = env.InstallAs('${MBN_ROOT}/amss.mbn', target_mbn)

 

 

 

由於有:

ifeq ($(USES_HW6500),yes)

    BOOT = $(SRCROOT)/drivers/boot

 

else

    ifeq ($(IMAGE), APPS_PROC)

        BOOT = $(SRCROOT)/core/api/boot/appsproc/

        APPSBL = $(BOOT)

    else

        BOOT=$(SRCROOT)/core/api/boot/

    BOOT +=$(SRCROOT)/core/api/boot/amssboot/

    endif

 

endif

且咱們定義 APPS_MODEM ,因此使用的是:

BOOT=$(SRCROOT)/core/api/boot/

BOOT +=$(SRCROOT)/core/api/boot/amssboot/

 

boot_reset_handler.s 使用的是:

./AMSS/products/7x30/core/boot/amssboot/shared/src/boot_reset_handler.s

...

EXPORT  Reset_Handler

EXPORT  soft_breakpoints_enabled

Reset_Handler

    ;------------------------------------------------------------------

    ; process init - initializes the AMSS process

    ; returns the number of bytes to pop off the stack

    ;------------------------------------------------------------------

    ldr     r0, [sp]

    blx     process_init

    add     sp, sp, r0

 

soft_breakpoints_enabled ; All pages of apps code have been paged in.

    ;------------------------------------------------------------------

    ; Pop argc and argv and launch into main.  If main is compiled with

    ; thumb mode, blx will ensure that we properly change to thumb mode

    ;------------------------------------------------------------------

    ldmia   sp!, {r0}

    mov     r1, sp

    blx     main

...

 

 

./AMSS/products/7x30/core/boot/amssboot/shared/src/boot_vectors.s:49:        IMPORT  Reset_Handler

./AMSS/products/7x30/core/boot/amssboot/shared/src/boot_vectors.s:102:        DCD       Reset_Handler

 

 

 

 

./AMSS/products/7x30/core/bsp/amsslibs/build/qdsp5/SConscript:102:   install_temp_adsp_mbn = env.InstallAs(adsp_mbn_path, adsp_bin_path)

./AMSS/products/7x30/core/bsp/amsslibs/build/qdsp5/SConscript:108:   install_adsp_mbn = env.InstallAs('${MBN_ROOT}/adsp.mbn', ADSP_mbn)

./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/SConscript:193:   install_target_reloc = env.InstallAs(AMSS_RELOC, target_elf)

./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/SConscript:203:   install_target_pbn = env.InstallAs(BOOTING_PBN, target_pbn)

./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/SConscript:215:   install_quartz_constant_cmm = env.InstallAs(

./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/SConscript:261:   install_target_mbn = env.InstallAs("${MBN_ROOT}/amss.mbn", target_mbn)

./AMSS/products/7x30/core/bsp/coreimg/build/arm11/CoreImage.py:240:      install_target_mbn = env.InstallAs('${MBN_ROOT}/amss.mbn', target_mbn)

1.3.3.10.1  

1.3.3.11 partition規則解析

1.3.3.11.1 eMCC 啓動和 NAND 啓動的分區格式是不同的,若是是 eMCC 啓動,多了編譯選項:

USES_SDCC_BOOT=yes USES_HSU_MS_FD_BOOT=yes

若是 USES_HSU_MS_FD_BOOT=yes

=== Compiling  boot/osbl/fd_storage_scsi.c

=== Compiling  boot/osbl/fd_storage_usb.c

若是 USES_SDCC_BOOT=yes

那麼會進行 partition 規則的處理,它會覆蓋掉 corebsp_build 規則階段生成的 partition.mbn

./AMSS/products/7x30/build/ms/dmss_rules.min

-----------

   。。。

partition :

    @echo Generate partition.bin.....

    @$(GENERATE_PARTITION)

   。。。

不一樣 modem 版本中,GENERATE_PARTITION 的定義會不一樣

HY11-N0723-1_1.2.00  中爲:

-------

define GENERATE_PARTITION

        @echo ------------------------------------------------------------------

        @echo Changing to Tools directory...

        @pwd

        cd $(TOOLSDIR_JSDCC); make; make genpart

endef

-------

HY11-N1496-2_1.2.40 中爲:

-------

define GENERATE_PARTITION

        @echo ------------------------------------------------------------------

        @echo Changing to Tools directory...

        @pwd

        cd $(TOOLSDIR_JSDCC); make; make genpart

        perl $(TOOLSDIR_JSDCC)/partition_extract_mbr.pl 2 0 $(TOOLSDIR_JSDCC)/

        rm -f $(MBNPATH)/partition.mbn

        rm -f $(MBNPATH)/ENPRG7x30.hex

        cp -f $(TOOLSDIR_JSDCC)/partition.mbn $(MBNPATH)/

        cp -f $(MBNPATH)/MPRG7x30.hex $(MBNPATH)/ENPRG7x30.hex

        cp -f $(MBNPATH)/MPRG7x30.hex $(MBNPATH)/NPRG7x30.hex

endef

------

partition 規則主要完成如下功能:

1) 編譯 ./AMSS/products/7x30/core/storage/tools/jsdcc/partition_load_pt 代碼,生成 loadpt 和 msp

2) 解析 loadpt 解析 partition.xml 文件,把分區信息保存成二進制文件 partition.bin

3) 由 partition.bin 文件生成 partition.mbn,而後拷貝到 ./AMSS/products/7x30/build/ms/bin/AAABQMAZ/partition.mbn

-----

cd $(TOOLSDIR_JSDCC); make; make genpart 命令會到目錄:

./AMSS/products/7x30/core/storage/tools/jsdcc/ 下執行 make; make genpart

由於有:

./AMSS/products/7x30/core/storage/tools/jsdcc/partition_load_pt/Makefile

   。。。

all:   $(TARGET_LOADPT)$(EXE) $(TARGET_MSP)$(EXE)

genpart:

    ./$(TARGET_LOADPT)$(EXE)

   。。。

因此 make 命令會生成 loadpt 和 mps

make genpart 執行 loadpt 命令

 

-------------

loadpt 命令解析 partition.xml 文件分析:

fp_input = fopen("partition.xml", "rt"); 打開文件:

AMSS/products/7x30/core/storage/tools/jsdcc/partition_load_pt/partition.xml

 

#define INPUT_BUFFER_SIZE     10240

input_buf = malloc(INPUT_BUFFER_SIZE);

申請一個大小爲 10240的緩衝區,對 partition.xml 文件內容進行解析,而後以串的形式保存在變量: input_buf 中。

 

fp_bin_out = fopen("partition.bin", "wb");

生成一個 partition.bin 文件,用於保存二進制的分區信息

 

parse_element(input_buf, LEVEL_IMAGE);

對每一個分區描述符進行解析,而後保存到文件 partition.bin 中。

---------------

命令 perl $(TOOLSDIR_JSDCC)/partition_extract_mbr.pl 2 0 $(TOOLSDIR_JSDCC)/ 會生成文件:

./AMSS/products/7x30/core/storage/tools/jsdcc/partition_load_pt/partition.mbn

---------------

./AMSS/products/7x30/core/bsp/tools/emmcbld/build/MPRG7x30.hex

./AMSS/products/7x30/build/ms/bin/AABBQOLY/MPRG7x30.hex

 

在 HY11-N0216-4_1.2.20 版本中不存在文件

./AMSS/products/7x30/core/bsp/tools/emmcbld/build/MPRG7x30.hex

 

1.4 高通平臺 7630 啓動流程分析

1.4.1 啓動流程概述

開機後,首先從 rom 中的 pbl 開始執行,pbl 裝載 dbl

1.4.2 pbl 流程

pbl 是固化在高通芯片中的一段程序,沒有相應的源代碼。

1.4.3 dbl 流程

pbl運行之後,它會裝載 dbl,dbl是從其__main 函數開始執行,此函數在彙編文件 dbl.s 中。

./AMSS/products/7x30/core/boot/secboot2/dbl/shared/src/dbl.s

__main

_main

    ...

    ldr    r5, =dbl_main_ctl   

    blx    r5

    ...

經過 dbl_main_ctl 調用會進入 c 函數, dbl_main_ctl 函數在文件:

./AMSS/products/7x30/core/boot/secboot2/dbl/shared/src/dbl_mc.c:282中:

void dbl_main_ctl(boot_pbl_shared_data_type *pbl_shared)

    ...

    調用表 dbl_init_func_tbl 中的每一個函數

    for ( i=0; dbl_init_func_tbl[i] != NULL; i++ )

    {

        dbl_init_func_tbl[i](&dbl_shared_data);

    }

    ...

    #通過一系列的初始化,dbl 會把控制權傳遞給 osbl

    dbl_shared_data.entry_ptr(dbl_shared_data.dbl_data_for_osbl);

    ...

 

dbl_init_func_tbl 表在文件:

./AMSS/products/7x30/core/boot/secboot2/dbl/shared/src/dbl_mc.c:122 中,其中的函數:

dbl_load_osbl_image 會完成 osbl 的裝載

dbl_load_osbl_image 函數在文件:

./AMSS/products/7x30/core/boot/secboot2/dbl/shared/src/dbl_loader.c:322 中:

void dbl_load_osbl_image(dbl_shared_data_type *shared_data)

{

  dbl_error_type ret_value = DBL_ERR_NONE;

  ret_value = dbl_load_image(shared_data, OSBL_IMG);

  DBL_VERIFY((ret_value == DBL_ERR_NONE),  (uint32)ret_value);

} /* dbl_load_osbl_image */

 

dbl_load_osbl_image

    ret_value = dbl_load_image(shared_data, OSBL_IMG);

        shared_data->dbl_state = DBL_STATE_LOAD_OSBL_IMG;

        ret_value = dbl_load_hdr_and_image(  shared_data,img_type,MIBIB_OSBL_PARTI_NAME,MI_OSBL_MAGIC1,MI_OSBL_MAGIC2);

           shared_data->entry_ptr      = (void (*)(void*))(image_hdr.image_dest_ptr);

 

dbl_shared_data.entry_ptr(dbl_shared_data.dbl_data_for_osbl)

在調用 dbl_shared_data.entry_ptr 以前,已經對該函數指針進行了初始化:

shared_data->entry_ptr      = (void (*)(void*))(image_hdr.image_dest_ptr);

它其實是指向 osbl 鏡像的起始地址,因此執行以後,系統進入 osbl 階段

1.4.4 osbl 流程

osbl 的入口函數 __main 在彙編文件:

./AMSS/products/7x30/core/boot/secboot2/osbl/shared/src/osbl.s:86: 中

    ...

    IMPORT osbl_main_ctl

    ...

    AREA    OSBL_ENTRY, CODE, READONLY

    CODE32

    ENTRY       

__main

_main

    ...

    ldr    r5, =osbl_main_ctl   

    blx    r5

    ...

 

__main 函數會調用 osbl_main_ctl ,此函數在文件:

./AMSS/products/7x30/core/boot/secboot2/osbl/shared/src/osbl_mc.c:234 中。

void osbl_main_ctl(boot_dbl_if_shared_info_type *dbl_shared_info_ptr)

{

    ...

    #Process the target-dependent OSBL procedures

    osbl_do_procedures( &bl_shared_data,osbl_main_procs );

    ...

    //把控制權給 AMSS

    bl_shared_data.amss_entry_ptr();

 

}

在此階段,osbl 經過 osbl_main_procs 中定義的 osbl_load_appsbl 函數把應用程序的控制權交給了android 系統,modem 端的控制權經過 bl_shared_data.amss_entry_ptr() 交割 AMSS,他們分別在兩個處理器上同時運行,兩個處理期間經過 smd 進行通訊。

osbl_main_procs 在文件:

./AMSS/products/7x30/core/boot/secboot2/osbl/target/msm7x30/src/osbl_mc_target.c:524中,它定義了一些初始化函數:

osbl_procedure_func_type osbl_main_procs[] =

{

   ...

   //初始化 迷你usb 充電硬件

   osbl_hw_init,

   ...

   //在 osbl 階段會提高系統時鐘

   #ifndef RUMIBUILD

    osbl_increase_clk_speed,

   #endif

   ...

   //初始化 osbl 模而且鎖住接口

  

   osbl_init_modules,

   ...

   初始化 flash 設備

   osbl_flash_init,

   ...

   //檢測是否經過sd卡更新鏡像文件

   osbl_sd_image_upgrade,

   ...

   //初始化數據結構,以便裝載 AMSS 鏡像

   osbl_init_amss_image,

   ...

#ifdef FEATURE_FOTA

  /*-----------------------------------------------------------------------

   * Initialize FOTA

   *-----------------------------------------------------------------------*/

  osbl_fota_init,

#endif /* FEATURE_FOTA */

   //amss 鏡像進行受權鑑定 

   osbl_auth_amss_image,

   //若是有 adsp 那麼進行相應處理

#ifdef FEATURE_OSBL_LOAD_AND_BOOT_ADSP

   //裝載 adsp 鏡像

  osbl_load_adsp,

  //受權

  osbl_auth_adsp,  

#endif 

 

#ifdef FEATURE_SDCC_BOOT

   //裝載 amss 鏡像

   osbl_load_amss_image,

   ...

#endif

 

#ifndef FEATURE_STANDALONE_MODEM

   //從flash 設備裝載 appsboot

   osbl_load_appsbl,

   ...

   //從flash中裝載 OS 鏡像

   * Load the OS image from flash

   osbl_load_apps_os,

   //引導 aARM 處理器

   osbl_boot_aarm,

#endif /* FEATURE_STANDALONE_MODEM */

  對於 nand 啓動,AMSS 應該在 apps 引導之後再裝載

#ifndef FEATURE_SDCC_BOOT

   // nand 啓動,裝載 amss 鏡像

   osbl_load_amss_image,

#endif

   ...

};

 

1.4.4.1 osbl 裝載 appsbl 過程分析

osbl 經過 osbl_load_appsbl 函數裝載應用程序的 boot loader 到指定的 RAM 中

osbl_load_appsbl 在文件:

./AMSS/products/7x30/core/boot/secboot2/osbl/shared/src/osbl_aarm_boot.c:119 中

void osbl_load_appsbl( bl_shared_data_type *bl_shared_data )

{

...

/*從 flash 中裝載 appsbl 頭和鏡像到 RAM 中*/

    osbl_load_header_and_image_with_cookie( APPSBL_IMG, &appsbl_image_header_with_cookie );

... 

/*若是 boot loader 沒有裝載到地址 0x0, 那麼將會拷貝 appsbl 向量表到地址 0x0, appsbl 鏡像的向量表老是在在鏡像的頭 64字節中*/

 

  if ( apps_image_start_addr != 0x0 )

  {

/* 爲 L4 with kernel entry 初始化復位向量,其餘的向量賦值爲 無限循環*/

復位向量的初始化值與 appsbl 鏡像起始地址有關,復位的時候此值會被放入到 PC 寄存器

向量 0x00000020 中保存 appsbl 鏡像的起始地址

向量 0x00000000 中的值爲 0xE59FF018

    address 0x00000000:     ldr pc, [pc, #0x18]

address 0x00000020:     apps_image_start_addr */   

 

    uint32 *vector_ptr = (uint32*) 0x00000020;   

    *vector_ptr = apps_image_start_addr;

    for ( --vector_ptr; vector_ptr; vector_ptr-- )

    {

      *vector_ptr = 0xEAFFFFFE;         /* Infinite loop */

    }

    *vector_ptr  = 0xE59FF018;          /* ldr pc, [pc, #0x18] */

  }

} /* osbl_load_appsbl() */

osbl_load_header_and_image_with_cookie 函數完成 appsbl 鏡像頭和鏡像的裝載,它首先會嘗試從 mibi 中裝載 appsbl 鏡像頭,若是當前是 nor non-partition table 設備,那麼裝載將會成功,若是不成功,那麼認爲 appsbl 頭位於它分區的起始位置,將其讀出。

 

1.4.5 appsbl 流程(源代碼在 android中)

appsbl 是 applications ARM boot loader 的簡稱,不一樣的軟件框架,此分區來自不一樣的源代碼

在android 系統中  appsbl 代碼爲 bootable/bootloader/lk

brew 框架的系統中 appsbl 代碼在 ./AMSS/products/7x30/core/boot/appsproc/target/msm7x30/src

brew 框架系統,入口函數 __main -> appsbl_main_ctl 在文件:

./AMSS/products/7x30/core/boot/appsproc/target/msm7x30/src/appsbl_handler.s 中。

 

android 系統中有:

vendor/qcom/msm7630_surf/AndroidBoard.mk:25:

include bootable/bootloader/lk/AndroidBoot.mk

bootable/bootloader/lk/arch/arm/system-onesegment.ld

system-onesegment.ld 中 ENTRY(_start) 指定了 appsbl 分區從 _start 函數開始執行,此函數在文件 ./bootable/bootloader/lk/arch/arm/crt0.S:25 中:

...

.text

.globl _start

_start:

    b   reset

   ...

   bl      kmain

   ...

kmain 會跳轉到 C 文件中執行,此函數文件

bootable/bootloader/lk/kernel/main.c 中:

void kmain(void)

    thread_resume(thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));

static int bootstrap2(void *arg)

{

    arch_init();

    platform_init();

    target_init();

    apps_init();

    return 0;

}

 

apps_init 在文件:bootable/bootloader/lk/app/app.c:33 中:

/* one time setup */

void apps_init(void)

{

    const struct app_descriptor *app;

 

    /* call all the init routines */

    for (app = &__apps_start; app != &__apps_end; app++) {

       if (app->init)

           app->init(app);

    }

 

    /* start any that want to start on boot */

    for (app = &__apps_start; app != &__apps_end; app++) {

       if (app->entry && (app->flags & APP_FLAG_DONT_START_ON_BOOT) == 0) {

           start_app(app);

       }

    }

}

 

由於:bootable/bootloader/lk/include/app.h:45 中有:

#define APP_START(appname) struct app_descriptor _app_##appname __SECTION(".apps") = { .name = #appname,

#define APP_END };

bootable/bootloader/lk/app/aboot/aboot.c 中有:

APP_START(aboot)

    .init = aboot_init,

APP_END

因此有:

struct app_descriptor _app_aboot __SECTION(".apps") =

{

      .name = aboot,

      .init = aboot_init,

};

 

因此 apps_init 函數中的: app->init 實際上調用的是文件:

bootable/bootloader/lk/app/aboot/aboot.c:398 中的函數 aboot_init

 

1.4.5.1 aboot_init 過程分析(須要側重關心的部分)

aboot_init 階段咱們應該關心 fastboot 模式 和 appsbl 對 android 系統的引導過程。

void aboot_init(const struct app_descriptor *app)

{

        unsigned reboot_mode = 0;

    page_size = flash_page_size();

    page_mask = page_size - 1;

    if (keys_get_state(KEY_HOME) != 0)

            boot_into_recovery = 1;

    if (keys_get_state(KEY_BACK) != 0)

       goto fastboot;

    if (keys_get_state(KEY_CLEAR) != 0)

       goto fastboot;

 

    reboot_mode = check_reboot_mode();

        if (reboot_mode == RECOVERY_MODE){

            boot_into_recovery = 1;

        }else if(reboot_mode == FASTBOOT_MODE){

            goto fastboot;

        }

recovery_init();

    //從falsh上讀取 linux 而後引導

    boot_linux_from_flash();

    dprintf(CRITICAL, "ERROR: Could not do normal boot. Reverting "

       "to fastboot mode.\n");

 

fastboot:

        display_init();

    dprintf(INFO, "Diplay initialized\n");

    udc_init(&surf_udc_device);

 

    fastboot_register("boot", cmd_boot);

    fastboot_register("erase:", cmd_erase);

    fastboot_register("flash:", cmd_flash);

    fastboot_register("continue", cmd_continue);

    fastboot_register("reboot", cmd_reboot);

    fastboot_register("reboot-bootloader", cmd_reboot_bootloader);

    fastboot_publish("product", "swordfish");

    fastboot_publish("kernel", "lk");

 

    fastboot_init((void*) SCRATCH_ADDR, 100 * 1024 * 1024);

    udc_start();

}

 

recovery_init() 調用的是文件 bootable/bootloader/lk/app/aboot/recovery.c中的函數:

/* Read and write the bootloader command from the "misc" partition.

 * These return zero on success.

 */

從 misc 分區讀取

 

 

struct bootloader_message {

    char command[32];

    char status[32];

    char recovery[1024];

};

 

/* Read and write the bootloader command from the "misc" partition.

 * These return zero on success.

 */

int get_bootloader_message(struct bootloader_message *out);

int set_bootloader_message(const struct bootloader_message *in);

 

/* Write an update to the cache partition for update-radio or update-hboot.

 * Note, this destroys any filesystem on the cache partition!

 * The expected bitmap format is 240x320, 16bpp (2Bpp), RGB 5:6:5.

 */

int write_update_for_bootloader(

        const char *update, int update_len,

        int bitmap_width, int bitmap_height, int bitmap_bpp,

        const char *busy_bitmap, const char *error_bitmap);

 

ROM上又分爲幾個分區:boot, system, recovery, cache, userdata和misc。在boot上存着bootloader和Linux Kernel,system上面是Android系統,userdata包含登陸信息/我的軟件和設置等。recovery區裏放着的是如何控制系統恢復的工具,如Google官方的stock恢復器。系統開機的時候,bootloader會首先檢查硬件配置,而後將Radio Firmware寫入RAM,接着調進kernel,最後再裝載Android OS進入桌面

misc - misc分區,通常不會去動它,和咱們沒有太大關係

recovery -recovery分區

boot - 存儲linux系統內核的分區,包括 kernel 和 ramdisk 兩部分

system -系統分區,儲存着Android系統的數據,刷 ROM 主要刷的是這個

cache -緩存分區,刷ROM時最好一塊兒擦一下

Dalvik-cache- 這個是Android使用的Java虛擬機的緩存分區,刷ROM時最好一塊兒擦一下

userdata - 用戶本身使用的數據部分,存儲咱們本身的軟件設置等等,恢復出廠設置的時候,這個分區會被格式化

還有Radio,這個部分一般負責無線信號,能夠理解爲手機信號收發部分的驅動,不過N1的視頻編碼器也集成在這裏面,Radio能夠隨便刷,不過某些特定的ROM可能會指定Radio版本。

最後是SPL/Bootloader,這個咱們通常不會用到它也不會修改它,除了第一次解鎖的時候(不過解鎖信息儲存在哪裏,如今xda上也沒有定論,彷佛不是在SPL裏面,這個大體至關於電腦上的 BIOS,負責整個手機的最底層引導,壞了可能致使變磚。

 

recovery 分區的 init.rc 文件比較簡單

./out/target/product/msm7630_surf/recovery/root/init.rc

service recovery /sbin/recovery

service adbd /sbin/adbd recovery

on property:persist.service.adb.enable=1

    start adbd

on property:persist.service.adb.enable=0

    stop adbd

它只啓動了 /sbin/recovery /sbin/adbd

Recovery 可執行程序的mian函數在

bootable/recovery/recovery.c

    ui_init(); 初始化 recovery 模式的界面

    get_args(&argc, &argv); 獲取按鍵選擇

 

 

prompt_and_wait()

install_package()

    handle_update_package()

        try_update_binary(path, zip)

           handle_firmware_update(firmware_type, firmware_filename, zip)

              remember_firmware_update(type, data, data_size)

                  update_type = type;

                  update_data = data;

                  update_length = length;

 

maybe_install_firmware_update(send_intent);

write_update_for_bootloader() 寫入數據

snprintf(boot.command, sizeof(boot.command), "update-%s", update_type);

set_bootloader_message(&boot)

纔是真正的更新 radio.img

 

 

一、下載最新的CursorSense的ROM:CursorSense32A-Mod-0.9.1.1-signed,和要求的RADIO(radio6.35.07.29.img),SPL(hboot1.76.2007.img),HERO的RECOVERY(recovery-RA-hero-v1.5.2.img)

二、在FASTBOOT下用下面的命令開刷(文件改過名):

fastboot flash hboot hboot.img

fastboot flash radio radio.img

fastboot erase system -w

fastboot erase boot

fastboot erase recovery

fastboot flash recovery recovery.img

 

 

1.4.5.1.1 fastboot 模式分析

1.4.5.1.1.1 什麼是 fastboot 模式

fastboot 是android 系統的軟件燒寫模式,經過它咱們能夠爲系統燒寫軟件

參考文檔:

工程模式與FASTBOOT

http://android.cool3c.com/article/2260

 

 

1.4.5.1.1.2 fastboot 模式與 recovery 模式的區別

fastboot 模式 和 recovery 模式都是 android系統的軟件燒寫或者升級方式,經過他們能夠爲機器燒寫軟件。

他們有以下區別:

1.  代碼來自不一樣分區,fastboot 在 appsbl 分區 ,recovery 是單獨的一個分區

2.  fastboot 比 recovery 功能更強,它能夠用來燒寫 recovery 分區

fastboot 能夠作的事情:

1.  重啓機器

2.燒寫分區

3. 擦除分區

4. 重啓 appsbl

5. 系統更新等
常有以下命令:
fastboot reboot         重啓機器
fastboot flash boot     boot.img    燒寫引導分區

fastboot flash system   system.img  燒寫系統分區
fastboot flash userdata data.img    燒寫數據分區
fastboot flash recovery recovery.img     燒寫恢復模式分區

fastboot flash splash1  mysplash.rgb565  燒寫開機畫面

fastboot erase  system  擦除系統分區
fastboot update update.zip  update.zip 是 boot.img, system.img和recovery.img的zip壓縮包

以上子命令不必定存在,要根絕實際狀況肯定。fastboot 中是經過 fastboot_register 方式註冊了一系列可用的子命令,如:

fastboot_register("boot", cmd_boot);

fastboot_register("erase:", cmd_erase);

fastboot_register("flash:", cmd_flash);

fastboot_register("continue", cmd_continue);

fastboot_register("reboot", cmd_reboot);

fastboot_register("reboot-bootloader", cmd_reboot_bootloader);

fastboot_register("getvar:", cmd_getvar);

fastboot_register("download:", cmd_download);

咱們能夠根絕實際狀況修改 fastboot 代碼,讓其支持更多命令,如:

fastboot flashall  在當前目錄尋找各類全部的image文件,在刷完全部分區後重啓手機

recovery 分區只能對 system ,data,cache boot 等分區進行燒寫,sd卡上放 update.zip 的升級方式就能夠經過 recovery 的方式完成。

 

 

除了 fastboot 模式能夠燒寫 recovery ,在 android 系統的命令模式下能夠經過 flash_image 命令

./out/target/product/msm7630_surf/symbols/system/bin/flash_image 進行燒寫。

flash_image recovery /sdcard/recovery.img  紅色部分是你解壓出的文件名包含後綴名
reboot recovery 
以後就能看到新的recovery 了
E/flash_image(   35): can't find recovery partition

參考資料:

最新Amon-RA 1.3.2 Recovery原創教程(完成)

http://www.androidin.net/bbs/thread-29285-1-1.html

 

 

 

1.4.5.1.1.3 怎樣進入 fastboot 模式

在系統啓動的 appsboot 階段,經過如下幾種方式能夠進入 fastboot 模式

1.   經過按鍵,如: KEY_BACK 或者 KEY_CLEAR 等

2.   當前系統的重啓模式,若是爲 FASTBOOT_MODE

3.   引導linux失敗

unsigned check_reboot_mode(void)

{

    unsigned mode[2] = {0, 0};

    unsigned int mode_len = sizeof(mode);

    unsigned smem_status;

 

    smem_status = smem_read_alloc_entry(SMEM_APPS_BOOT_MODE,

                  &mode, mode_len );

    if(smem_status)

    {

      dprintf(CRITICAL, "ERROR: unable to read shared memory for reboot mode\n");

      return 0;

    }

    return mode[0];

}

bootable/bootloader/lk/platform/msm_shared/smem.h:83:  SMEM_APPS_BOOT_MODE = 106

 

按鍵進入 fastboot 模式要根據實際狀況決定,由於這些在代碼中都是能夠更改的,參考文檔:

市面常見機器進入 Recovery 模式及 Fastboot 模式的方法:http://android.cool3c.com/article/12221

 

1.4.5.1.1.4 android 系統手機刷機過程分析(補充知識)

將以 G1 爲樣機分析刷機過程

放到SD卡根目錄(不要更名,直接丟進去)
打開終端輸入
su(回車r)
mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system (回車)
cd sdcard (回車r)
flash_image recovery recovery-RAv1.2.1G.img (回車)
以上是從一個帖子裏找來的。上面說不要更名,我改了名字刷成功了。

 

 

1.4.5.1.2 appsbl 引導 android 系統

appsbl 對 android 系統的引導是從 boot_linux_from_flash 開始,它首先引導 linux 內核,而後由 linux 內核裝載引導上層的 android 系統。

boot_linux_from_flash() 函數在文件:

bootable/bootloader/lk/app/aboot/aboot.c:182 中。

它其實是從 boot 分區中讀取 boot.img (內核+ramdisk)而後引導執行,具體過程以下:

int boot_linux_from_flash(void)

{

    struct boot_img_hdr *hdr = (void*) buf;

    unsigned n;

    struct ptentry *ptn;

    struct ptable *ptable;

    unsigned offset = 0;

    const char *cmdline;

 

        首先判斷是否爲 eMMC啓動

    if (target_is_emmc_boot()) {

       hdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;

       if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {

           dprintf(CRITICAL, "ERROR: Invalid boot image header\n");

           return -1;

       }

       goto continue_boot;

    }

        獲取分區表

    ptable = flash_get_ptable();

    if (ptable == NULL) {

       dprintf(CRITICAL, "ERROR: Partition table not found\n");

       return -1;

    }

        若是不是進入 recovery 模式

    if(!boot_into_recovery)

    {

            ptn = ptable_find(ptable, "boot");

            if (ptn == NULL) {

               dprintf(CRITICAL, "ERROR: No boot partition found\n");

               return -1;

            }

    }

        //進入 recovery 模式

    else

    {

            ptn = ptable_find(ptable, "recovery");

            if (ptn == NULL) {

               dprintf(CRITICAL, "ERROR: No recovery partition found\n");

               return -1;

            }

    }

        //讀取 boot.img

    if (flash_read(ptn, offset, buf, page_size)) {

       dprintf(CRITICAL, "ERROR: Cannot read boot image header\n");

       return -1;

    }

    offset += page_size;

 

    if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {

       dprintf(CRITICAL, "ERROR: Invaled boot image heador\n");

       return -1;

    }

 

    if (hdr->page_size != page_size) {

       dprintf(CRITICAL, "ERROR: Invaled boot image pagesize. Device pagesize: %d, Image pagesize: %d\n",page_size,hdr->page_size);

       return -1;

    }

        //獲取 kernel 鏡像文件地址

    n = ROUND_TO_PAGE(hdr->kernel_size, page_mask);

    if (flash_read(ptn, offset, (void *)hdr->kernel_addr, n)) {

       dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");

       return -1;

    }

    offset += n;

        //獲取 ramdisk 鏡像文件地址

    n = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);

    if (flash_read(ptn, offset, (void *)hdr->ramdisk_addr, n)) {

       dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");

       return -1;

    }

    offset += n;

 

continue_boot:

    dprintf(INFO, "\nkernel  @ %x (%d bytes)\n", hdr->kernel_addr,

       hdr->kernel_size);

    dprintf(INFO, "ramdisk @ %x (%d bytes)\n", hdr->ramdisk_addr,

       hdr->ramdisk_size);

 

    if(hdr->cmdline[0]) {

       cmdline = (char*) hdr->cmdline;

    } else {

       cmdline = DEFAULT_CMDLINE;

    }

    dprintf(INFO, "cmdline = '%s'\n", cmdline);

 

    /* TODO: create/pass atags to kernel */

        //開始引導內核

    dprintf(INFO, "\nBooting Linux\n");

    boot_linux((void *)hdr->kernel_addr, (void *)TAGS_ADDR,

          (const char *)cmdline, board_machtype(),

          (void *)hdr->ramdisk_addr, hdr->ramdisk_size);

 

    return 0;

}

 

boot_linux 調用的文件:

bootable/bootloader/lk/app/aboot/aboot.c:94 中的函數:

void boot_linux(void *kernel, unsigned *tags,

       const char *cmdline, unsigned machtype,

       void *ramdisk, unsigned ramdisk_size)

{

    ...

    void (*entry)(unsigned,unsigned,unsigned*) = kernel;

    ...

    entry(0, machtype, tags);

}

 

entry(0, machtype, tags); 正式進入內核,將由kernel 完成 android 系統的啓動。

 

 

====================================

 

osbl_load_appsbl:

  This function loads the applications ARM boot loader to its

  destination RAM.  It may load the aARM from flash or from data

  contained within the OEM SBL image depending on OEM security

  requirements. 

 

osbl_load_apps_os:

 This function loads the APPS image from flash to its destination

 address in RAM. A cookie read from the APPSBL header is checked for

 the size of OS image and magic number. If the magic number matches and

 the size of apps image is greater than 0, the image is loaded. 

 

osbl_load_apps_os 函數在文件:

./AMSS/products/7x30/core/boot/secboot2/osbl/shared/src/osbl_aarm_boot.c:394 中:

void osbl_load_apps_os( bl_shared_data_type *bl_shared_data )

    /* Initialize unified boot interface */

    unified_boot_init(&appsbl_image_header_with_cookie);

 

./AMSS/products/7x30/core/boot/tools/headergen/shared/src/image_header.c:492:     

    boot_cookie.OS_type = atoi(argv[i+5]);

    header[12] = boot_cookie.OS_type;       /* OS type to boot */

 

nand_tools 工具來自源代碼:

 

編譯腳本:

./AMSS/products/7x30/core/bsp/tools/flash/nand_exe/build/SConscript

========================================

env.Replace(TARGET_NAME = 'nand_tools')

nand_tools_exe = env.Program('${TARGET_NAME}', source=[], LIBS=libs, LIBPATH=libs_path)

# copy elf and reloc to needed locations for AMSS tools to load on target

install_target_exe = env.Install(SRCPATH, nand_tools_exe)

========================================

nand_tools 工具語法:

./AMSS/products/7x30/core/bsp/tools/flash/nand_exe/build/nand_tools -fp flash_page_size -fb flash_block_size -fd flash_device_size -d device_bootloader_fname -u usr_partition_fname -m mibib_partition_fname -p binary_folder_path

 

 

 

 

 

 

每個燒寫的 *.mbn 都有一個標準的頭,它由函數

 

  /*----------------------------------------------------------------------

    Fill up header structure

  ----------------------------------------------------------------------*/

  header[0] = id;

  header[2] = image_source;

  header[3] = image_dest;

  header[4] = image_size;/* image_size */

  header[5] = code_size; /* code_size */

  header[6] = image_dest+code_size; /* signature_ptr */

  header[7] = signature_size;            /* signature_size */

  header[8] = image_dest+code_size+signature_size;/* cert_chain_ptr */

  header[9] = cert_chain_size;                    /* cert_chain_size*/

  header[10] = UNIFIED_BOOT_COOKIE_MAGIC_NUMBER; /* boot cookie magic number */

  header[11] = 0;                         /* cookie version number */

  header[12] = boot_cookie.OS_type;       /* OS type to boot */   

  header[13] = 0;          /* start address of apps partition in storage device */

  header[14] = boot_cookie.boot_apps_size_entry; /* size in bytes of apps kernel to be loaded */

  header[15] = boot_cookie.boot_apps_ram_loc; /* location in RAM to load apps kernel */

  header[16] = 0;          /* reserve pointer */

  header[17] = 0;          /* reserve for future use */

  header[18] = 0;          /* reserve for future use */

  header[19] = 0;          /* reserve for future use */

  printf("image_size = 0x%X, code_size= =0x%X\n", image_size, code_size);

 

  /*----------------------------------------------------------------------

    Open output header file

  ----------------------------------------------------------------------*/

由於文件:

./AMSS/products/7x30/build/ms/boot_targets_nonsec.min:346

./AMSS/products/7x30/build/ms/boot_targets_sec.min:498

中有:

GEN_AMSS_HEADER    = $(HEADERGEN)/image_header $(FLASH_TYPE) amss $(MBNPATH)/amss.mbn $(MBNPATH)/amsshd.mbn

語法以下:

Usage: ./AMSS/products/7x30/tools/headergen/image_header flash_type header_type input_code_file \

output_header_file secure_type [dbl_preamble_file or elf_src_file]

例如:

./AMSS/products/7x30/tools/headergen/image_header nand amss ./AMSS/products/7x30/build/ms/bin/AAABQMAZ/amss.mbn amssh.mbn  dbl_preamble_file

 

 

./AMSS/products/7x30/tools/headergen/image_header "nand" amss ./AMSS/products/7x30/build/ms/bin/AAABQMAZ/amss.mbn ./aaahd.mbn

 

文件: ./AMSS/products/7x30/build/ms/dmss_flags.min:131: 中有:

ifeq ($(USES_NOR16_CFG_DATA)$(USES_NOR32_CFG_DATA),yes)#  NAND or NOR

  FLASH_TYPE=nor

else

  FLASH_TYPE=nand

endif

從咱們的環境變量能夠知道使用的是 nand flash

#pragma RUNLOCAL 

$(MBNPATH)/amsshd.mbn: $(IMAGE_HEADER) $(MBNPATH)/amss.mbn

    @echo ---------------------------------------------------------------

    @echo Generating image header for AMSS.

    @echo

    @$(GEN_AMSS_HEADER)

    @echo ---------------------------------------------------------------

1.4.5.1.2.1 Android 系統啓動過程當中存在的問題

1.4.5.1.1.1.1 linker 問題致使系統沒法啓動

高通 sdk 打印信息:

D/qemud   (   37): fdhandler_accept_event: accepting on fd 10

D/qemud   (   37): created client 0xe078 listening on fd 8

D/qemud   (   37): client_fd_receive: attempting registration for service 'boot-properties'

D/qemud   (   37): client_fd_receive:    -> received channel id 1

D/qemud   (   37): client_registration: registration succeeded for client 1

I/qemu-props(   47): connected to 'boot-properties' qemud service.

I/qemu-props(   47): received: qemu.sf.lcd_density=160

I/qemu-props(   47): received: dalvik.vm.heapsize=16m

D/qemud   (   37): fdhandler_accept_event: accepting on fd 10

D/qemud   (   37): created client 0xe078 listening on fd 11

D/qemud   (   37): fdhandler_event: disconnect on fd 11

D/qemud   (   37): fdhandler_accept_event: accepting on fd 10

D/qemud   (   37): created client 0xe078 listening on fd 11

D/qemud   (   37): client_fd_receive: attempting registration for service 'gsm'

D/qemud   (   37): client_fd_receive:    -> received channel id 2

D/qemud   (   37): client_registration: registration succeeded for client 2

 

經過ps能夠看出,主要是由於 zygote 未能正常啓動,手動啓動該服務:

/system/bin/app_process -Xzygote /system/bin --zygote &

彈出一些錯誤信息:

# link_image[1729]:    71 could not load needed library 'libandroid_runtime.so' for '/system/bin/app_process' (link_image[1729]:    71 could not load needed library 'libnativehelper.so' for 'libandroid_runtime.so' (link_image[1729]:    71 could not load needed library 'libicudata.so' for 'libnativehelper.so' (alloc_mem_region[823]: OOPS:    71 cannot map library 'libicudata.so'. no vspace available.)))CANNOT LINK EXECUTABLE

從以上信息能夠判定,是應用程序在linker的時候未能裝載須要的庫,致使服務終止。

由於咱們目前編譯的sdk和generic版本都是給予 armv5te ,而高通是 armv7 因此暫時不建議修改代碼

咱們能夠先從網上 sdk 的 elair版本中考取 linker 文件,拷貝到:

out/target/product/generic/system/bin/  而後從新打包 system.img : make snod

bionic/linker/linker.c

#define LINKER_BASE ((LINKER_TEXT_BASE) & 0xfff00000)

#define LINKER_TOP  (LINKER_BASE + (LINKER_AREA_SIZE))

======標準代碼========

LINKER_TEXT_BASE := 0xB0000100

LINKER_AREA_SIZE := 0x01000000

#define LIBBASE 0x80000000

#define LIBLAST 0x90000000

LINKER_BASE=0xB0000000

======高通======

LINKER_TEXT_BASE := 0x70000100

LINKER_AREA_SIZE := 0x01000000

#define LIBBASE 0x40000000

#define LIBLAST 0x50000000

#define R_ARM_REL32      3

LINKER_BASE=0x70000000

===============

R_ARM_ABS32 32bit 絕對地址重定位引用

R_ARM_PC24  24bit PC相對地址重定位引用

R_ARM_ABS32 32bit 絕對地址重定位引用

R_ARM_REL32 32bit 相對地址重定位引用

REL 是 relative 的縮寫,是以當前指令結束時的EIP爲參考地址

ABS 是 absolute 的縮寫,指絕對地址.

rel32 當即數

r32   寄存器

m32   內存訪問

 

1.4.6 AMSS 流程

osbl 階段,經過函數 osbl_load_amss_image 裝載 amss 鏡像文件

void osbl_load_amss_image( bl_shared_data_type *bl_shared_data )

{

    ...

/* 獲取 elf 文件的入口點 */

     bl_shared_data->amss_entry_ptr = (amss_entry_ptr_type) boot_sec_elf_get_entry_point( bl_shared_data->amss_elf_if );

    ...  

} /* osbl 裝載 amss 鏡像文件 */

 

在 osbl_main_ctl 函數中經過 bl_shared_data.amss_entry_ptr() 把控制權交給了 AMSS。

在文件:

AMSS/products/7x30/core/kernel/arch/arm/pistachio/src/gnu/linker.lds:33: 中有:

ENTRY(_start)

因此能夠肯定 AMSS 的鏡像是從 _start 函數開始執行,該函數在文件:

AMSS/products/7x30/core/kernel/arch/arm/pistachio/src/head.spp:51: 中 

。。。   

BEGIN_PROC(_start)

。。。

        /* Jump to startup_system */

        adr     r0,     __phys_addr_ram

        bl      arch_init

。。。

 

Amss 鏡像由幾部分組成,

AMSS/products/7x30/core/kernel/tools/amss.py

def get_amss_kernel_platform_src(build_asic, build_target, platform_dir):

platform_src = ["%s/src/" % platform_dir + fn for fn in ["plat_asm.spp", "timer.cc", "irq.cc", "plat.cc", "init_warm.cc", "head.spp" ]]

 

AMSS/products/7x30/core/kernel/arch/arm/pistachio/src/head.spp:51:       

BEGIN_PROC(_start)

 

TASK_COMMON_SOURCES =  [

   '${BUILDPATH}/mobile.c',

   '${BUILDPATH}/task.c',

   '${BUILDPATH}/task_iram.c'

]

task_objs = env.Object(TASK_COMMON_SOURCES)

task_lib = env.Library('${BUILDPATH}/task', task_objs)

./AMSS/products/7x30/core/debugtools/task/build/corelibs/arm11/task.lib

 

env.AddLibsToImage(['MODEM_IMAGE', 'CBSP_MODEM_IMAGE'],

   [task_lib,

   task_dog_lib,

   task_dog_keepalive_modem_lib,

   task_dog_keepalive_client_lib])

 

./AMSS/products/7x30/core/bsp/build/scripts/utils.py:59:  

env.AddMethod(add_libs_to_image, "AddLibsToImage")

./AMSS/products/7x30/core/bsp/build/scripts/utils.py:140:

def add_libs_to_image(env, targets, libs):

./AMSS/products/7x30/core/bsp/amsslibs/build/arm11/SConscript:65:env.Replace(MODEM_IMAGE = env.subst('${PROC}'))

./AMSS/products/7x30/core/bsp/build/msm7x30_modem.mak:34:PROC = MULTI_PROC

IMAGE=MODEM_PROC

 

./AMSS/products/7x30/modem/rfa/rf/task/common/inc/rf_task.h:79:TASK_START_SIG     0x8000

./AMSS/products/7x30/core/boot/appsproc/target/msm7x30/src/process.c:31:                   SMSM RESET state to process_restart from err.c.

./AMSS/products/7x30/core/debugtools/err/src/err.c:808:      process_restart();

 

err_fatal_jettison_core

    -> err_fatal_handler

 

 

    代碼運行到了Main()以後,在這個函數裏面將完成操做系統(rex)的初始化工做,其實現方法是調用rex_init()。Rex_init()完成的工做很簡單:

完成操做系統必要的一些數據結構(timer鏈表、任務鏈表等))的初始化以外;

接下來,它建立了三個任務,分別是:rex_idle_task、rex_dpc_task和tmc_task。

Idle任務沒什麼好解釋的,目前這個任務爲空,什麼也沒作,dpc_task目前不知道是作什麼的,暫時能夠不用管。前面的這兩個任務都屬於操做系統層面的,由操做系統來維護,和手機軟件關係不大。哪個和手機軟件關係大呢?答案是:tmc_task。你們能夠把這個看成操做系統的入口(主)任務,也能夠把它看成整個手機軟件的入口任務。即AMSS軟件裏的全部其它任務的建立和維護就是由這個tmc_task來完成的。

    到此爲止,整個AMSS軟件還並無跑起來,只是跑到了tmc_task裏面了。在tmc_task裏面,會調用tmc_init()來完成整個AMSS軟件包的初始化工做,其中最重要的一項工做就是調用tmc_define_tasks()將AMSS軟件包全部須要的任務都建立起來了。好比說slee_task、dog_task、cm_task、wms_task、ui_task等。這些任務,通常不須要直接和AL層軟件打交道,但請你們記住,手機上全部功能的實現最根本點就是由這些服務組件(Service Task)來完成的。未來你們跟蹤一個具體的功能模塊時,好比說通話模塊,若是須要,能夠再去深刻研究它的具體實現。

    好了,到如今爲止,全部的AMSS核心軟件就所有跑起來了(手機的功能模塊,在軟件方面就體現爲OS層面的一個任務)。但如今你們還根本看不到Brew和AEE的影子。呵呵,各位不要急。到了這個層面以後,我想稍微多說幾句。最先的Qualcomm平臺,好比說5xxx系列,是根本沒有Brew的,那個時候的AL(Application Layer)層軟件開發,是直接調用底層Service task所提供的API來完成相應的工做的。從這種角度來看的話,顯然那時的開發是比較鬱悶和難度較高的。不過,到了65xx以後,Qualcomm平臺引入了Brew,手機開發商就不必去從這麼底層(Service API)的層面進行手機開發了,他們徹底能夠基於Brew來實現一臺手機的全部功能(Qualcomm給咱們的參考代碼,就是全Brew平臺的)。

    Brew的運行環境AEE是如何跑起來的呢?關鍵在於ui_task(),因爲ui_task和咱們手機開發的關係很是密切,其地位也至關重要,因此,後文我將單獨對它進行一個深刻的研究與分析。到目前爲止,你們只須要知道ui_task將AEE加載起來了,而且,它起到了一箇中間層的做用,即全部AMSS底層服務組件的消息,都將經由ui_task而轉到AEE,並最終轉到具體的App(Applet)的執行代碼裏面(HandleEvent())。

注意:

上述的開機過程,在每一次按開機鍵都須要走一遍,即關機以後,整個系統的全部功能都將消失,而不像有些手機,看起來是關了機,但實際上底層仍是有一些軟件模塊在跑。爲何能夠確定地說上述開機過程每次都必須走一遍,緣由很簡單,由於咱們的平臺軟件是基於Nand Flash啓動的,全部的代碼都須要Copy到SDRAM才能運行,而關機斷電以後,SDRAM裏的東東會所有丟失,因此,毫無疑問,上述的過程必須每次開機都執行;

關機的過程相對比較簡單,系統檢測到關機中斷以後,將調用tmc_powerdown_handler()來完成關機動做,它將把全部AMSS的任務都Stop掉,並最後調用rex_exit()退出Rex,從而完成整個關機動做。

顯然,關機動做前,若是有必要,每個任務必須將它但願保存的信息保存到Flash上面,以便下次開機時能夠獲得這些信息;

開機流程簡圖

 EMBED Visio.Drawing.11  

圖1 Qualcomm平臺開機框圖

    說明:

Tmc是操做系統層面和AMSS軟件關係最密切的一個任務,不過須要OEM商在此處修改的地方應該很少;

ui_task是在操做系統層面,OEM商須要重點研究清楚的一個任務,它是鏈接底層Task和上層AL的一箇中間層,有可能須要加入OEM商的操做流程;

CoreApp是在Brew層面的一個AL層的入口Applet,它其着管理整個上層AL層軟件的做用,根據產品需求,這個App須要定作;

AEE是整個上層App的運行環境,目前Qualcomm沒有公開它的源碼,但它的運行機制,Amoi須要好好研究清楚,我將在另一篇《Qualcomm平臺AEE運行機制深刻分析與研究》中探討它的運行機理和調度機制,你們有興趣能夠參考此文;

Boot代碼深刻分析

Boot代碼大部分是用匯編語言寫的,也有小部分,可能須要由OEM商修改,因此用C語言來寫。另外,Boot代碼屬於Driver範圍,因此你們能夠在drivers/boot目錄裏面找到相應的代碼。Boot的代碼組織得很是模塊化,整個boot的入口點是在Boot_function_table.s裏面,這個彙編代碼裏面其實是將Boot須要完成的任務封裝成了不一樣的函數,由不一樣的函數來完成相應的工做,接下來,我將深刻分析這些函數所完成的工做,以下所述。

mmu_enable_instruction_cache;

這個只有在Nand啓動模式時才須要,打開ARM的指令Cache.

boot_hw_ctrl_init

此函數主要是完成兩條總線(EBI一、EBI2)控制器的初始化,這個函數執行完了       以後,系統就能夠知道兩條總線上鏈接了哪些設備,同時也能夠找獲得這些       設備,不過,至於單個設備自身的初始化,則不在這裏.

[注]

這個函數很重要,OEM商若是須要加新的設備到系統中(掛在兩條總線上),則需

要定作此模塊,目前階段主要是內存。另外,如前文所述,這個函數是由C語言

來寫的,主要目的就是爲了方便OEM商定作。內存設備的修改,能夠在這個模塊

裏找到相應的數據結構,相對仍是比較簡單的。

boot_hw_tlmm_init

1.晶振時鐘的初始化;

2.中斷表的初始化;

3.GPIO的初始化;

4.Msm自己的驅動,除了EBI2;

boot_rom_test

這個函數很是簡單,只是作一個很簡單的Rom檢查.(比對兩個標誌位來檢查,並

沒有一塊一塊地去檢查)。

boot_ram_test

Ram自檢,具體算法其實也很簡單,就是讀、寫內存以判斷是否成功.

boot_ram_init

1.拷貝手機代碼從Nand Flash到SDRAM。

a.Image__BB_RAM__Base:Core Code;

    b.Image__APP_RAM__Base:App Code;

    [注]

    上述動做是分塊進行的,緣由是由於Qualcomm支持分塊Boot Load.

2.將Image__ZI_REGION__ZI區域初始化爲0;

3.初始化OEM要求的動態Heap;

4.至於代碼段裏的數據初始化,直接在Image裏就完成了(編譯器完成);

boot_stack_initialize

ARM棧初始化,主要是爲分塊代碼加載而預留的.

boot_cache_mmu_init

ARM Mmu初始化

    注意:

       到此爲止,整個Boot的工做就告完結了,那麼,它又是如何跳到AMSS的main

入口點呢?緣由很簡單,ARM編譯器在連接的時候會自動作出一個__rt_entry(),

由此函數來完成ARM庫函數的初始化,並最後將代碼執行點跳轉到main()。而

__rt_entry()會在boot_reset_handler.s裏調用,具體細節,你們能夠不用太過關心,

只須要明白,Boot跑完以後,手機軟件就跑到了main裏就Ok了。

Ui_task的深刻分析

從大的方向來說,ui_task只完成兩件事,一件是必要的初始化工做(這個也是咱們所關心的,即ui_task到底完成了哪些工做);另一件事就是各類信號量的事件處理,這也是咱們比較關心的,即ui_task到底將哪些事件轉發給了上層App。搞清楚了上述兩點,咱們也就能大體把ui_task的承上啓下的工做機理研究清楚。

ui_Init;

初始化過程當中,ui_task主要完成了以下幾件事。

建立一個用於Kick Watchdog的定時器,這樣WatchDog可以及時獲得Kick,假現在後發現手機在ui_task裏面自動重啓,頗有可能就是這個定時器的Timeout設置得太短而形成的;

註冊通話相關的回調,主要是和緊急呼叫相關;

電話本初始化,之因此要進行這個工做,主要是加快開機以後AL層軟件操做電話本的速度,但這樣將有可能致使開機速度過慢,若是開機速度過慢,能夠考慮進入待機界面以後,在後臺開一個task去完成這項工做;

初始化Sound設備;

向底層服務任務wms_task註冊wms回調,這個回調是在IWms組件裏實現的。從這種角度來看,u幫咱們把wms_task和IWMS組件聯繫起來了,但並無去將AL層軟件和IWMS聯繫起來,這個工做將是由AL層軟件本身去完成。固然,註冊回調的這個工做也是能夠在AL層完成,之因此在這裏完成,而不是在AL層完成,其主要目的是這個工做能夠作到與AL層無關,即AL層不須要關心這個事情,但這個事情是短消息功能得於實現的必須步驟;

註冊鍵盤消息回調;

經過這個回調,全部的按鍵消息都將經由底層的hs_task傳到此回調函數裏。而後回調函數將把全部的按鍵信息放到一個全局變量ui_key_buffer裏面,接着發送一個UI_KEY_SIG信號給ui_task通知它去處理按鍵信息,至於ui_task如何處理按鍵消息的,後面的ui_handleSignals裏會有詳細描述。

初始化Lcd,這個工做不是LCD硬件設備的真正初始化,只是一些UI須要用到的LCD數據結構的初始化,和咱們關係不大;

[注]

硬件的初始化,所有都在hs_task裏面完成,從這種角度來看的話,系統能跑到ui_task裏面,代表全部的硬件設備的驅動都已經成功加載。

置開機標誌ui_powerup爲True;

註冊IPC信號量UI_IPC_SIG,這個能夠暫時無論;

bridle_InitSWITable的初始化,這個目標,暫時不知道,也能夠先略過;

初始化資源文件,其主要工做就是在Rom裏面創建資源文件的符號鏈表,這樣就可讓系統找到這些資源文件了(資源文件是被編譯在代碼段的,假如不這樣作的話,系統將找不到這些資源文件);

Brew運行環境AEE的初始化:AEE_Init,這個函數看不到代碼,你們只須要知道,到了這一步,整個Brew也就Run起來了,在AEE初始化完成以後,它將自動啓動一個Applet,即CoreStartApp,而CoreStartApp將把CoreApp啓動起來;

到此爲止,ui_task的初始化工做完成;

[注意]

    1) 從上述的ui_task的初始化工做能夠看出,ui_task並無完成手機AL層軟件的

基本功能的初始化,好比說Sim卡檢測、網絡初始化等,這些工做,應該是在

CoreApp裏完成的

       2) 真正和手機功能相關的初始化工做,是在CoreApp裏完成的,這個Applet的工

做機理,後面也會有詳細描述;

ui_HandleSignals;

ui_task主要完成以下事件的處理。

看門狗餵食;

TASK_STOP_SIG信號,任務Stop,目前這個任務爲空,沒作任何事;

TASK_OFFLINE_SIG的處理,這幾個任務都屬於操做系統層面的事件,目前咱們能夠暫時無論;

處理關機信號:CoreAppHandleStopSig(),這個只是處理ui_task在關機前須要完成的任務,好比說發送一個消息給CoreApp讓它關掉本身,而後將ui_task關閉;

[A]

系統的真正關機信號是由tmc來處理,當它發現須要關機時,調用tmc_powerdown_handler來完成相應的工做,在這裏就是給全部的任務發送TASK_STOP_SIG的信號。

[A]

深層次的關機處理,不須要咱們瞭解,也不必去知道,咱們只須要知道在ui_task裏面把該關的關掉就Ok了。

[A]

關機是一個層層深刻的過程,每個App或者任務只須要負責將它們本身建立的資源釋放掉就Ok了。而關機的導引線,顯然是在CoreApp裏截獲到關機鍵以後發送出來的,事實上也是如此。

網絡掉線時,發送掉線信號給CoreApp;

[A]

其實這個信號徹底能夠在CoreApp裏面,本身去註冊,而後及時更新本身的網絡狀態,就不知有沒有這種接口函數。

處理按鍵消息,其主要完成以下的工做:

打開背光;

特理按鍵到虛鍵值的轉換;

按鍵聲音的處理;

將按鍵消息傳送到AEE執行環境,由它去負責按鍵的派發;

[注]

1.背光的打開是由ui默認完成的,那這樣的話,假如我不想按鍵時有背光,是否可行?看來就得修改此處的代碼;

2.AEE的按鍵派發機制如何?它可否保證處於顯示最上層的App永遠是能夠獲得Key的App,即假如一個Applet將自身Hide,它是否依然能夠獲得Key,而其它的Applet是否就不能夠獲得了?很怕也像EMP同樣出現焦點丟失的狀況;

處理AEE_APP_SIG信號量,完成AEE的調度工做,這個任務是ui完成的最重要的一項工做,由於上層的App須要定時進行調度,目前看來,這個調度工做是由AEE_APP_SIG觸發的,而AEE_APP_SIG這個信號量,則由操做系統層面的一個定時器定時發送的。如今你們只要瞭解,AEE_Dispatch會定時調用就Ok了,至於更詳細的AEE調度機制,能夠參考個人另一篇《AEE運行機制深刻分析與研究》;

處理AEE_SIO_SIG信號量,這個看不到代碼,暫時略過無論;

結論

經過上述對於ui_task的分析,能夠看出,ui_task真正和手機功能有關係的(便可能須要定製或者修改的地方),主要就是初始化資源文件和處理按鍵消息這兩部分。至於其它部分,目前都不須要Amoi關心。手機真正功能的實現,好比說開機Logo的顯示、Sim卡的檢查、Pin碼校驗等,都是在CoreApp裏面完成的。

其它

CoreApp的深刻分析

目前參考代碼裏面的CoreApp所完成的工做比較多且雜,主要說來有以下幾件事。

系統組件初始化;

開機Logo的顯示;

Sim卡檢測和Pin碼校驗;

系統狀態信息更新;

電池狀態;

網絡信號;

網絡模式;

IAnnunciator的維護與更新;

通話處理,打電話的輸入框;

主菜單處理;

手機各類設置功能的處理;

關機鍵的處理;

目前CoreApp裏面的代碼,完成了太多的事,其實徹底能夠剝離成不一樣的模塊來完成,大體能夠分紅以下幾個部分。

總控模塊;(CoreApp)

總控模塊,主要完成手機按下開機鍵以後的各類初始化工做,同時此模塊也是整個手機的控制中心,由它來完成手機的一些全局性工做,主要有以下幾項。

系統初始化、Sim卡檢測和Pin碼校驗;

開機Logo或者開機動畫的顯示;

底層服務程序的啓動;(WmsApp、DialApp等);

系統配置信息的統一管理;

因爲寫配置信息到NV上面是一件很是慢的工做,每次上層App改變配置以後都去操做NV,很影響速度。因此,能夠在內存中開一個配置信息的Buffer,上層App操做的其實是這個Buffer,而後由Core在空閒的時候再統一寫到NV上去。

關機處理;

[注]

因爲CoreApp是在Idle Applet的界面之下,因此,爲了可以實現「一鍵回菜單」的功用,有可能須要修改ui_task裏面的Key處理函數,將全部的Key消息轉發給Core,這樣Core就能夠獲得全部的Key事件了。(如今的ui_task只把Key事件發送給了AEE,而AEE只會將Key事件發送給當前活動Applet)。

Idle模塊;

主要完成待機界面的畫圖工做,主要有兩部分:

系統信息指示欄;

待機界面(位圖、動畫、時鐘、日曆等);

軟鍵

[注]

Idle只負責界面工做,不負責具體的系統狀態信息的獲取工做,這個工做將由其它模塊完成。

Polling

手機狀態信息查詢模塊,主要是完成手機各類狀態信息的更新與維護。主要有以下幾種:

電池強度;

網絡信號強度;

網絡模式(C/G);

PLMN網絡名;

短消息、通話狀態、鬧鈴;(這個由專門的模塊完成,不在Polling之列);

各類外設信息;(USB、耳機插入等);

其它各類雜項信息;

Menu模塊

菜單模塊主要分兩部分,一部分是主菜單的實現,另外一個子菜單的實現。通常來說,手機上的菜單系統應該是由Menu模塊去統一完成,而不是由每個子程序去手動完成。菜單模塊通常只須要負責到主菜單、二級菜單和三級菜單就Ok了。三級菜單以後的界面,就由每個App單獨去維護了。

其它功能App模塊;

每個功能模塊,由一個專門的App來完成,這樣的話,模塊的獨立性強,便於單獨開發。模塊間經過App啓動和消息傳送的方式來發生關係和進行模塊間通訊。

 

後記

到此爲止,Qualcomm整個手機從按下開機鍵到跑到主菜機界面,整個流程一目瞭然。對於Amoi而言,目前須要關心和定作的部分其實很少,最頭疼的 當屬CoreApp的改造工做,固然這個就是後話了,筆者將在從此的文章中加以詳述。

但願本文對於你們理解Qualcomm手機軟件的運行流程有必定的幫助,若是有什麼問題,請直接聯繫我,最後謝謝你們耐心把本文看完,謝謝。

參考文檔

a)         80-V1072-1_E_Boot_Block_Downloader.pdf

b)        80-V5316-1_K_QCT_Ext_API_RG.pdf

c)         driver/boot目錄源碼

d)        service/tmc目錄源碼

e)         app/core目錄源碼

 

 

REX啓動分析——基於Qualcomm平臺

http://hi.baidu.com/gcmao/blog/item/5ef1ea2c12da08341e308914.html

Qualcomm手機開機全過程

Qualcomm手機開機全過程大揭密(四)

http://www.1mp.cn/DataShow.aspx?id=1642

 

 

Qualcomm手機開機全過程大揭密

chh@amoi.com.cn

2004-11-13

摘要:

    本文試圖經過代碼來深刻剖析Qualcomm手機開機的整個過程,即從按下開機鍵一直到出現待機界面,Qualcomm的手機軟件在整個流程中究竟完成了哪些工做。本文的主要目標是理清手機的初始化流程,併爲從此Amoi定作初始化工做提供一個參考。

關鍵字:開機、Rex、TMC、ui_task、CoreApp

開機的簡要流程分析

Qualcomm的平臺軟件支持兩種啓動方式:一種是Nor Flash啓動方式,另一種就

是Nand Flash啓動方式。Nor Flash啓動方式就至關於硬件直接找到一個入口點開始執行代碼,相比較而言會 比較簡單,且Amoi沒有采用此種方式,因此本文對於這種方式不作詳細分析。另一種就是Nand Flash啓動方式,這種方式和PC的啓動方式比較相像,也是Amoi採用的Boot方式,下面將詳細分析在此方式下面的開機過程。

    按下開機鍵以後,將產生一個時鐘中斷,從而通知AMSS主芯片的Boot Load硬件去將放置於Nand Flash上面的第一個Block(8K)裏面的Boot代碼Copy到內核內存(RAM,這個內存應該是CPU自帶的內存,同後面提到的SDRAM有必定區別,能夠把它看成CPU的Cache)的0xFFFF0000地址,並開始執行Boot代碼。Boot的主要任務是完成整個系統的硬件初始化工做(相似於PC上面的BIOS所完成的硬件自檢工做,至於Boot的詳細工做機制,後文會有詳細描述)。Boot所完成的工做裏面,最重要的一件事就是會將整個手機軟件代碼(AMSS軟件包)拷貝到SDRAM中,並最後將控制權交給AMSS軟件。說白了,就是Boot執行完成以後,代碼的執行點將由Boot跳轉到AMSS軟件的的入口點函數main().(此函數在mobile.c裏實現)。

    代碼運行到了Main()以後,在這個函數裏面將完成操做系統(rex)的初始化工做,其實現方法是調用rex_init()。Rex_init()完成的工做很簡單:

完成操做系統必要的一些數據結構(timer鏈表、任務鏈表等))的初始化以外;

接下來,它建立了三個任務,分別是:rex_idle_task、rex_dpc_task和tmc_task。

Idle任務沒什麼好解釋的,目前這個任務爲空,什麼也沒作,dpc_task目前不知道是作什麼的,暫時能夠不用管。前面的這兩個任務都屬於操做系統層面的,由操做系統來維護,和手機軟件關係不大。哪個和手機軟件關係大呢?答案是:tmc_task。你們能夠把這個看成操做系統的入口(主)任務,也能夠把它看成整個手機軟件的入口任務。即AMSS軟件裏的全部其它任務的建立和維護就是由這個tmc_task來完成的。

    到此爲止,整個AMSS軟件還並無跑起來,只是跑到了tmc_task裏面了。在tmc_task裏面,會調用tmc_init()來完成整個AMSS軟件包的初始化工做,其中最重要的一項工做就是調用tmc_define_tasks()將AMSS軟件包全部須要的任務都建立起來了。好比說slee_task、dog_task、cm_task、wms_task、ui_task等。這些任務,通常不須要直接和AL層軟件打交道,但請你們記住,手機上全部功能的實現最根本點就是由這些服務組件(Service Task)來完成的。未來你們跟蹤一個具體的功能模塊時,好比說通話模塊,若是須要,能夠再去深刻研究它的具體實現。

    好了,到如今爲止,全部的AMSS核心軟件就所有跑起來了(手機的功能模塊,在軟件方面就體現爲OS層面的一個任務)。但如今你們還根本看不到Brew和AEE的影子。呵呵,各位不要急。到了這個層面以後,我想稍微多說幾句。最先的Qualcomm平臺,好比說5xxx系列,是根本沒有Brew的,那個時候的AL(Application Layer)層軟件開發,是直接調用底層Service task所提供的API來完成相應的工做的。從這種角度來看的話,顯然那時的開發是比較鬱悶和難度較高的。不過,到了65xx以後,Qualcomm平臺引入了Brew,手機開發商就不必去從這麼底層(Service API)的層面進行手機開發了,他們徹底能夠基於Brew來實現一臺手機的全部功能(Qualcomm給咱們的參考代碼,就是全Brew平臺的)。

    Brew的運行環境AEE是如何跑起來的呢?關鍵在於ui_task(),因爲ui_task和咱們手機開發的關係很是密切,其地位也至關重要,因此,後文我將單獨對它進行一個深刻的研究與分析。到目前爲止,你們只須要知道ui_task將AEE加載起來了,而且,它起到了一箇中間層的做用,即全部AMSS底層服務組件的消息,都將經由ui_task而轉到AEE,並最終轉到具體的App(Applet)的執行代碼裏面(HandleEvent())。

注意:

上述的開機過程,在每一次按開機鍵都須要走一遍,即關機以後,整個系統的全部功能都將消失,而不像有些手機,看起來是關了機,但實際上底層仍是有一些軟件模塊在跑。爲何能夠確定地說上述開機過程每次都必須走一遍,緣由很簡單,由於咱們的平臺軟件是基於Nand Flash啓動的,全部的代碼都須要Copy到SDRAM才能運行,而關機斷電以後,SDRAM裏的東東會所有丟失,因此,毫無疑問,上述的過程必須每次開機都執行;

關機的過程相對比較簡單,系統檢測到關機中斷以後,將調用tmc_powerdown_handler()來完成關機動做,它將把全部AMSS的任務都Stop掉,並最後調用rex_exit()退出Rex,從而完成整個關機動做。

顯然,關機動做前,若是有必要,每個任務必須將它但願保存的信息保存到Flash上面,以便下次開機時能夠獲得這些信息;

開機流程簡圖

 EMBED Visio.Drawing.11  

圖1 Qualcomm平臺開機框圖

    說明:

Tmc是操做系統層面和AMSS軟件關係最密切的一個任務,不過須要OEM商在此處修改的地方應該很少;

ui_task是在操做系統層面,OEM商須要重點研究清楚的一個任務,它是鏈接底層Task和上層AL的一箇中間層,有可能須要加入OEM商的操做流程;

CoreApp是在Brew層面的一個AL層的入口Applet,它其着管理整個上層AL層軟件的做用,根據產品需求,這個App須要定作;

AEE是整個上層App的運行環境,目前Qualcomm沒有公開它的源碼,但它的運行機制,Amoi須要好好研究清楚,我將在另一篇《Qualcomm平臺AEE運行機制深刻分析與研究》中探討它的運行機理和調度機制,你們有興趣能夠參考此文;

Boot代碼深刻分析

Boot代碼大部分是用匯編語言寫的,也有小部分,可能須要由OEM商修改,因此用C語言來寫。另外,Boot代碼屬於Driver範圍,因此你們能夠在drivers/boot目錄裏面找到相應的代碼。Boot的代碼組織得很是模塊化,整個boot的入口點是在Boot_function_table.s裏面,這個彙編代碼裏面其實是將Boot須要完成的任務封裝成了不一樣的函數,由不一樣的函數來完成相應的工做,接下來,我將深刻分析這些函數所完成的工做,以下所述。

mmu_enable_instruction_cache;

這個只有在Nand啓動模式時才須要,打開ARM的指令Cache.

boot_hw_ctrl_init

此函數主要是完成兩條總線(EBI一、EBI2)控制器的初始化,這個函數執行完了       以後,系統就能夠知道兩條總線上鏈接了哪些設備,同時也能夠找獲得這些       設備,不過,至於單個設備自身的初始化,則不在這裏.

[注]

這個函數很重要,OEM商若是須要加新的設備到系統中(掛在兩條總線上),則需

要定作此模塊,目前階段主要是內存。另外,如前文所述,這個函數是由C語言

來寫的,主要目的就是爲了方便OEM商定作。內存設備的修改,能夠在這個模塊

裏找到相應的數據結構,相對仍是比較簡單的。

boot_hw_tlmm_init

1.晶振時鐘的初始化;

2.中斷表的初始化;

3.GPIO的初始化;

4.Msm自己的驅動,除了EBI2;

boot_rom_test

這個函數很是簡單,只是作一個很簡單的Rom檢查.(比對兩個標誌位來檢查,並

沒有一塊一塊地去檢查)。

boot_ram_test

Ram自檢,具體算法其實也很簡單,就是讀、寫內存以判斷是否成功.

boot_ram_init

1.拷貝手機代碼從Nand Flash到SDRAM。

a.Image__BB_RAM__Base:Core Code;

    b.Image__APP_RAM__Base:App Code;

    [注]

    上述動做是分塊進行的,緣由是由於Qualcomm支持分塊Boot Load.

2.將Image__ZI_REGION__ZI區域初始化爲0;

3.初始化OEM要求的動態Heap;

4.至於代碼段裏的數據初始化,直接在Image裏就完成了(編譯器完成);

boot_stack_initialize

ARM棧初始化,主要是爲分塊代碼加載而預留的.

boot_cache_mmu_init

ARM Mmu初始化

    注意:

       到此爲止,整個Boot的工做就告完結了,那麼,它又是如何跳到AMSS的main

入口點呢?緣由很簡單,ARM編譯器在連接的時候會自動作出一個__rt_entry(),

由此函數來完成ARM庫函數的初始化,並最後將代碼執行點跳轉到main()。而

__rt_entry()會在boot_reset_handler.s裏調用,具體細節,你們能夠不用太過關心,

只須要明白,Boot跑完以後,手機軟件就跑到了main裏就Ok了。

Ui_task的深刻分析

從大的方向來說,ui_task只完成兩件事,一件是必要的初始化工做(這個也是咱們所關心的,即ui_task到底完成了哪些工做);另一件事就是各類信號量的事件處理,這也是咱們比較關心的,即ui_task到底將哪些事件轉發給了上層App。搞清楚了上述兩點,咱們也就能大體把ui_task的承上啓下的工做機理研究清楚。

ui_Init;

初始化過程當中,ui_task主要完成了以下幾件事。

建立一個用於Kick Watchdog的定時器,這樣WatchDog可以及時獲得Kick,假現在後發現手機在ui_task裏面自動重啓,頗有可能就是這個定時器的Timeout設置得太短而形成的;

註冊通話相關的回調,主要是和緊急呼叫相關;

電話本初始化,之因此要進行這個工做,主要是加快開機以後AL層軟件操做電話本的速度,但這樣將有可能致使開機速度過慢,若是開機速度過慢,能夠考慮進入待機界面以後,在後臺開一個task去完成這項工做;

初始化Sound設備;

向底層服務任務wms_task註冊wms回調,這個回調是在IWms組件裏實現的。從這種角度來看,u幫咱們把wms_task和IWMS組件聯繫起來了,但並無去將AL層軟件和IWMS聯繫起來,這個工做將是由AL層軟件本身去完成。固然,註冊回調的這個工做也是能夠在AL層完成,之因此在這裏完成,而不是在AL層完成,其主要目的是這個工做能夠作到與AL層無關,即AL層不須要關心這個事情,但這個事情是短消息功能得於實現的必須步驟;

註冊鍵盤消息回調;

經過這個回調,全部的按鍵消息都將經由底層的hs_task傳到此回調函數裏。而後回調函數將把全部的按鍵信息放到一個全局變量ui_key_buffer裏面,接着發送一個UI_KEY_SIG信號給ui_task通知它去處理按鍵信息,至於ui_task如何處理按鍵消息的,後面的ui_handleSignals裏會有詳細描述。

初始化Lcd,這個工做不是LCD硬件設備的真正初始化,只是一些UI須要用到的LCD數據結構的初始化,和咱們關係不大;

[注]

硬件的初始化,所有都在hs_task裏面完成,從這種角度來看的話,系統能跑到ui_task裏面,代表全部的硬件設備的驅動都已經成功加載。

置開機標誌ui_powerup爲True;

註冊IPC信號量UI_IPC_SIG,這個能夠暫時無論;

bridle_InitSWITable的初始化,這個目標,暫時不知道,也能夠先略過;

初始化資源文件,其主要工做就是在Rom裏面創建資源文件的符號鏈表,這樣就可讓系統找到這些資源文件了(資源文件是被編譯在代碼段的,假如不這樣作的話,系統將找不到這些資源文件);

Brew運行環境AEE的初始化:AEE_Init,這個函數看不到代碼,你們只須要知道,到了這一步,整個Brew也就Run起來了,在AEE初始化完成以後,它將自動啓動一個Applet,即CoreStartApp,而CoreStartApp將把CoreApp啓動起來;

到此爲止,ui_task的初始化工做完成;

[注意]

    1) 從上述的ui_task的初始化工做能夠看出,ui_task並無完成手機AL層軟件的

基本功能的初始化,好比說Sim卡檢測、網絡初始化等,這些工做,應該是在

CoreApp裏完成的

       2) 真正和手機功能相關的初始化工做,是在CoreApp裏完成的,這個Applet的工

做機理,後面也會有詳細描述;

ui_HandleSignals;

ui_task主要完成以下事件的處理。

看門狗餵食;

TASK_STOP_SIG信號,任務Stop,目前這個任務爲空,沒作任何事;

TASK_OFFLINE_SIG的處理,這幾個任務都屬於操做系統層面的事件,目前咱們能夠暫時無論;

處理關機信號:CoreAppHandleStopSig(),這個只是處理ui_task在關機前須要完成的任務,好比說發送一個消息給CoreApp讓它關掉本身,而後將ui_task關閉;

[A]

系統的真正關機信號是由tmc來處理,當它發現須要關機時,調用tmc_powerdown_handler來完成相應的工做,在這裏就是給全部的任務發送TASK_STOP_SIG的信號。

[A]

深層次的關機處理,不須要咱們瞭解,也不必去知道,咱們只須要知道在ui_task裏面把該關的關掉就Ok了。

[A]

關機是一個層層深刻的過程,每個App或者任務只須要負責將它們本身建立的資源釋放掉就Ok了。而關機的導引線,顯然是在CoreApp裏截獲到關機鍵以後發送出來的,事實上也是如此。

網絡掉線時,發送掉線信號給CoreApp;

[A]

其實這個信號徹底能夠在CoreApp裏面,本身去註冊,而後及時更新本身的網絡狀態,就不知有沒有這種接口函數。

處理按鍵消息,其主要完成以下的工做:

打開背光;

特理按鍵到虛鍵值的轉換;

按鍵聲音的處理;

將按鍵消息傳送到AEE執行環境,由它去負責按鍵的派發;

[注]

1.背光的打開是由ui默認完成的,那這樣的話,假如我不想按鍵時有背光,是否可行?看來就得修改此處的代碼;

2.AEE的按鍵派發機制如何?它可否保證處於顯示最上層的App永遠是能夠獲得Key的App,即假如一個Applet將自身Hide,它是否依然能夠獲得Key,而其它的Applet是否就不能夠獲得了?很怕也像EMP同樣出現焦點丟失的狀況;

處理AEE_APP_SIG信號量,完成AEE的調度工做,這個任務是ui完成的最重要的一項工做,由於上層的App須要定時進行調度,目前看來,這個調度工做是由AEE_APP_SIG觸發的,而AEE_APP_SIG這個信號量,則由操做系統層面的一個定時器定時發送的。如今你們只要瞭解,AEE_Dispatch會定時調用就Ok了,至於更詳細的AEE調度機制,能夠參考個人另一篇《AEE運行機制深刻分析與研究》;

處理AEE_SIO_SIG信號量,這個看不到代碼,暫時略過無論;

結論

經過上述對於ui_task的分析,能夠看出,ui_task真正和手機功能有關係的(便可能須要定製或者修改的地方),主要就是初始化資源文件和處理按鍵消息這兩部分。至於其它部分,目前都不須要Amoi關心。手機真正功能的實現,好比說開機Logo的顯示、Sim卡的檢查、Pin碼校驗等,都是在CoreApp裏面完成的。

其它

CoreApp的深刻分析

目前參考代碼裏面的CoreApp所完成的工做比較多且雜,主要說來有以下幾件事。

系統組件初始化;

開機Logo的顯示;

Sim卡檢測和Pin碼校驗;

系統狀態信息更新;

電池狀態;

網絡信號;

網絡模式;

IAnnunciator的維護與更新;

通話處理,打電話的輸入框;

主菜單處理;

手機各類設置功能的處理;

關機鍵的處理;

目前CoreApp裏面的代碼,完成了太多的事,其實徹底能夠剝離成不一樣的模塊來完成,大體能夠分紅以下幾個部分。

總控模塊;(CoreApp)

總控模塊,主要完成手機按下開機鍵以後的各類初始化工做,同時此模塊也是整個手機的控制中心,由它來完成手機的一些全局性工做,主要有以下幾項。

系統初始化、Sim卡檢測和Pin碼校驗;

開機Logo或者開機動畫的顯示;

底層服務程序的啓動;(WmsApp、DialApp等);

系統配置信息的統一管理;

因爲寫配置信息到NV上面是一件很是慢的工做,每次上層App改變配置以後都去操做NV,很影響速度。因此,能夠在內存中開一個配置信息的Buffer,上層App操做的其實是這個Buffer,而後由Core在空閒的時候再統一寫到NV上去。

關機處理;

[注]

因爲CoreApp是在Idle Applet的界面之下,因此,爲了可以實現「一鍵回菜單」的功用,有可能須要修改ui_task裏面的Key處理函數,將全部的Key消息轉發給Core,這樣Core就能夠獲得全部的Key事件了。(如今的ui_task只把Key事件發送給了AEE,而AEE只會將Key事件發送給當前活動Applet)。

Idle模塊;

主要完成待機界面的畫圖工做,主要有兩部分:

系統信息指示欄;

待機界面(位圖、動畫、時鐘、日曆等);

軟鍵

[注]

Idle只負責界面工做,不負責具體的系統狀態信息的獲取工做,這個工做將由其它模塊完成。

Polling

手機狀態信息查詢模塊,主要是完成手機各類狀態信息的更新與維護。主要有以下幾種:

電池強度;

網絡信號強度;

網絡模式(C/G);

PLMN網絡名;

短消息、通話狀態、鬧鈴;(這個由專門的模塊完成,不在Polling之列);

各類外設信息;(USB、耳機插入等);

其它各類雜項信息;

Menu模塊

菜單模塊主要分兩部分,一部分是主菜單的實現,另外一個子菜單的實現。通常來說,手機上的菜單系統應該是由Menu模塊去統一完成,而不是由每個子程序去手動完成。菜單模塊通常只須要負責到主菜單、二級菜單和三級菜單就Ok了。三級菜單以後的界面,就由每個App單獨去維護了。

其它功能App模塊;

每個功能模塊,由一個專門的App來完成,這樣的話,模塊的獨立性強,便於單獨開發。模塊間經過App啓動和消息傳送的方式來發生關係和進行模塊間通訊。

 

後記

到此爲止,Qualcomm整個手機從按下開機鍵到跑到主菜機界面,整個流程一目瞭然。對於Amoi而言,目前須要關心和定作的部分其實很少,最頭疼的 當屬CoreApp的改造工做,固然這個就是後話了,筆者將在從此的文章中加以詳述。

但願本文對於你們理解Qualcomm手機軟件的運行流程有必定的幫助,若是有什麼問題,請直接聯繫我,最後謝謝你們耐心把本文看完,謝謝。

參考文檔

f)         80-V1072-1_E_Boot_Block_Downloader.pdf

g)        80-V5316-1_K_QCT_Ext_API_RG.pdf

h)        driver/boot目錄源碼

i)          service/tmc目錄源碼

j)          app/core目錄源碼

 

1.5 android 系統重啓關機流程分析

1.5.1 c語言中調用 reboot 函數

bionic/libc/unistd/reboot.c:33:

int reboot (int  mode)

{

    return __reboot( LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, mode, NULL );

}

1.5.2 經過 adb 讓系統重啓

adb reboot recovery  進入 recovery 模式

adb reboot bootloader 進入 fastboot 模式

adb reboot-bootloader

adb reboot 不帶參數 系統正常重啓

adb 是pc端工具,adbd是服務端,運行在手機

adbd 讀取 socket 解析由 adb 傳過來的命令串

int service_to_fd(const char *name)

if(!strncmp(name, "reboot:", 7)) {

        void* arg = strdup(name + 7);

        if(arg == 0) return -1;

        ret = create_service_thread(reboot_service, arg);

 

system/core/adb/services.c:176:

void reboot_service(int fd, void *arg)

{

    。。。

    ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,

                    LINUX_REBOOT_CMD_RESTART2, (char *)arg);

    。。。

}

bionic/libc/kernel/common/linux/reboot.h

#define LINUX_REBOOT_CMD_RESTART 0x01234567

#define LINUX_REBOOT_CMD_HALT 0xCDEF0123

kernel/include/linux/reboot.h:33:

#define    LINUX_REBOOT_CMD_RESTART2   0xA1B2C3D4

 

arg 對應字符串: recovery  bootloader

./kernel/arch/arm/mach-msm/pm2.c

system/core/adb/commandline.c

if (!strcmp(argv[0], "reboot-bootloader"))

   snprintf(command, sizeof(command), "reboot:bootloader");

若是輸入 adb reboot-bootloader adb 會對該命令進行轉換 至關於執行 adb reboot bootloader

1.5.3 fastboot 模式下系統重啓

fastboot reboot  系統正常重啓

fastboot reboot-bootloader 重啓進入fastboot 模式

fastboot 是 appboot 提供的功能,能夠用它來燒寫 system 等鏡像文件

bootable/bootloader/lk/app/aboot/aboot.c

APP_START(aboot)

    .init = aboot_init,

void aboot_init(const struct app_descriptor *app)

    。。。

    fastboot_register("reboot", cmd_reboot);

    fastboot_register("reboot-bootloader", cmd_reboot_bootloader);

    。。。

void cmd_reboot(const char *arg, void *data, unsigned sz)

{

    dprintf(INFO, "rebooting the device\n");

    fastboot_okay("");

    reboot_device(0);

}

 

void cmd_reboot_bootloader(const char *arg, void *data, unsigned sz)

{

    dprintf(INFO, "rebooting the device\n");

    fastboot_okay("");

    reboot_device(FASTBOOT_MODE);

}

bootable/bootloader/lk/target/msm7630_surf/init.c:311:

void reboot_device(unsigned reboot_reason)

bootable/bootloader/lk/target/msm7627_ffa/init.c:174:

void reboot_device(unsigned reboot_reason)

void reboot_device(unsigned reboot_reason)

{

    reboot(reboot_reason);

}

調用的是c函數:

bionic/libc/unistd/reboot.c:33:

int reboot (int  mode)

{

    return __reboot( LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, mode, NULL );

}

bootable/bootloader/lk/app/aboot/aboot.c:59:

#define FASTBOOT_MODE   0x77665500

if (!strcmp(cmd, "bootloader")) {

           restart_reason = 0x77665500;

}

 

1.5.4 系統關機

正常按鍵關機

./frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.java

void showGlobalActionsDialog()

  mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());

調用文件:

./frameworks/policies/base/phone/com/android/internal/policy/impl/GlobalActions.java

中的函數:

public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned)

  mDialog = createDialog();

調用本文件中的函數:

private AlertDialog createDialog()

public void onPress() {

    ShutdownThread.shutdownAfterDisablingRadio(mContext, true);

}

調用文件:

./frameworks/policies/base/phone/com/android/internal/policy/impl/ShutdownThread.java

中的函數:

public static void shutdownAfterDisablingRadio(final Context context, boolean confirm)

  beginShutdownSequence(context)

調用本文件中的函數:

private static void beginShutdownSequence(Context context)

  sInstance.start()

進入關機線程的run函數:

public void run() {

首先關藍牙,關射頻,而後再關電源

    ...

    sBluetooth.disable(false)

    ...

    sPhone.setRadio(false)

    ...

    SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC);

    ...

        Power.shutdown()

}

frameworks/base/core/java/android/os/Power.java:92:   

public static native void shutdown();

frameworks/base/core/jni/android_os_Power.cpp:107:   

{ "shutdown", "()V", (void*)android_os_Power_shutdown },

jni 調用

static void android_os_Power_shutdown(JNIEnv *env, jobject clazz)

{

    sync();

#ifdef HAVE_ANDROID_OS

    reboot(RB_POWER_OFF);

#endif

}

由於有 bionic/libc/include/sys/reboot.h:42:

#define RB_POWER_OFF    LINUX_REBOOT_CMD_POWER_OFF

因此實際相對執行

reboot(LINUX_REBOOT_CMD_POWER_OFF);

__reboot( LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_POWER_OFF, NULL );

 

這裏的 __reboot 是libc中的系統調用

bionic/libc/arch-x86/syscalls/__reboot.S

/* autogenerated by gensyscalls.py */

#include <sys/linux-syscalls.h>

 

    .text

    .type __reboot, #function

    .globl __reboot

    .align 4

    .fnstart

 

__reboot:

    .save   {r4, r7}

    stmfd   sp!, {r4, r7}

    ldr     r7, =__NR_reboot

    swi     #0

    ldmfd   sp!, {r4, r7}

    movs    r0, r0

    bxpl    lr

    b       __set_syscall_errno

    .fnend

 

1.5.5 內核中的系統調用 reboot

__NR_reboot 執行的是內核中的系統調用:

kernel/kernel/sys.c:310:

SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,

       void __user *, arg)

{

    char buffer[256];

    int ret = 0;

 

    /* We only trust the superuser with rebooting the system. */

    if (!capable(CAP_SYS_BOOT))

       return -EPERM;

 

    /* For safety, we require "magic" arguments. */

    if (magic1 != LINUX_REBOOT_MAGIC1 ||

        (magic2 != LINUX_REBOOT_MAGIC2 &&

                    magic2 != LINUX_REBOOT_MAGIC2A &&

           magic2 != LINUX_REBOOT_MAGIC2B &&

                    magic2 != LINUX_REBOOT_MAGIC2C))

       return -EINVAL;

 

    /* Instead of trying to make the power_off code look like

     * halt when pm_power_off is not set do it the easy way.

     */

    if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)

       cmd = LINUX_REBOOT_CMD_HALT;

 

    lock_kernel();

    switch (cmd) {

    case LINUX_REBOOT_CMD_RESTART:

       kernel_restart(NULL);

       break;

 

    case LINUX_REBOOT_CMD_CAD_ON:

       C_A_D = 1;

       break;

 

    case LINUX_REBOOT_CMD_CAD_OFF:

       C_A_D = 0;

       break;

 

    case LINUX_REBOOT_CMD_HALT:

       kernel_halt();

       unlock_kernel();

       do_exit(0);

       panic("cannot halt");

 

    case LINUX_REBOOT_CMD_POWER_OFF:

       kernel_power_off();

       unlock_kernel();

       do_exit(0);

       break;

 

    case LINUX_REBOOT_CMD_RESTART2:

       if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {

           unlock_kernel();

           return -EFAULT;

       }

       buffer[sizeof(buffer) - 1] = '\0';

 

       kernel_restart(buffer);

       break;

 

#ifdef CONFIG_KEXEC

    case LINUX_REBOOT_CMD_KEXEC:

       ret = kernel_kexec();

       break;

#endif

 

#ifdef CONFIG_HIBERNATION

    case LINUX_REBOOT_CMD_SW_SUSPEND:

       ret = hibernate();

       break;

#endif

 

    default:

       ret = -EINVAL;

       break;

    }

    unlock_kernel();

    return ret;

}

void kernel_restart(char *cmd)

{

    kernel_restart_prepare(cmd);

    if (!cmd)

       printk(KERN_EMERG "Restarting system.\n");

    else

       printk(KERN_EMERG "Restarting system with command '%s'.\n", cmd);

    machine_restart(cmd);

}

kernel/kernel/sys.c:341:

void kernel_power_off(void)

{

    kernel_shutdown_prepare(SYSTEM_POWER_OFF);

    if (pm_power_off_prepare)

       pm_power_off_prepare();

    disable_nonboot_cpus();

    sysdev_shutdown();

    printk(KERN_EMERG "Power down.\n");

    machine_power_off();

}

 

./kernel/arch/arm/kernel/process.c:219:

void machine_restart(char *cmd)

{

    arm_pm_restart(reboot_mode, cmd);

}

 

void machine_power_off(void)

{

    if (pm_power_off)

       pm_power_off();

}

 

由於./kernel/arch/arm/mach-msm/pm2.c:1740:中有:

arm_pm_restart = msm_pm_restart;

pm_power_off = msm_pm_power_off;

因此 arm_pm_restart 調用的是:

static void msm_pm_restart(char str, const char *cmd)

{

    msm_rpcrouter_close();

    msm_proc_comm(PCOM_RESET_CHIP, &restart_reason, 0);

 

    for (;;)

       ;

}

pm_power_off 調用的是:

static void msm_pm_power_off(void)

{

    msm_rpcrouter_close();

    msm_proc_comm(PCOM_POWER_DOWN, 0, 0);

    for (;;)

       ;

}

msm_proc_comm 是芯片級別的操做

msm_proc_comm_reset_modem_now 對modem芯片進行重啓

kernel/arch/arm/mach-msm/proc_comm.c:98:

int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2)

{

    。。。

    writel(cmd, base + APP_COMMAND);

    writel(data1 ? *data1 : 0, base + APP_DATA1);

    writel(data2 ? *data2 : 0, base + APP_DATA2);

    。。。

}

內核裏面writel是如何實現的

http://blog.chinaunix.net/u2/77776/showart_1404857.html

補充信息:

static int msm_reboot_call

    (struct notifier_block *this, unsigned long code, void *_cmd)

{

    if ((code == SYS_RESTART) && _cmd) {

       char *cmd = _cmd;

       if (!strcmp(cmd, "bootloader")) {

           restart_reason = 0x77665500;

       } else if (!strcmp(cmd, "recovery")) {

           restart_reason = 0x77665502;

       } else if (!strcmp(cmd, "eraseflash")) {

           restart_reason = 0x776655EF;

       } else if (!strncmp(cmd, "oem-", 4)) {

           unsigned code = simple_strtoul(cmd + 4, 0, 16) & 0xff;

           restart_reason = 0x6f656d00 | code;

       } else {

           restart_reason = 0x77665501;

       }

    }

    return NOTIFY_DONE;

}

static struct notifier_block msm_reboot_notifier = {

    .notifier_call = msm_reboot_call,

};

static int __init msm_pm_init(void)

  register_reboot_notifier(&msm_reboot_notifier);

 

內核編譯相關:

kernel/arch/arm/mach-msm/pm2.c:1701:          restart_reason = 0x77665500;

kernel/arch/arm/mach-msm/pm.c:696:        restart_reason = 0x77665500;

kernel/arch/arm/mach-msm/Makefile:84: 

ifdef CONFIG_MSM_N_WAY_SMSM

    obj-$(CONFIG_PM) += pm2.o

else

    obj-$(CONFIG_PM) += pm.o

endif

 

kernel/arch/arm/configs/msm7630-perf_defconfig:256:CONFIG_MSM_N_WAY_SMSM=y

kernel/arch/arm/configs/msm7627-perf_defconfig:247:CONFIG_MSM_N_WAY_SMSM=y

make -C kernel O=../out/target/product/msm7627_ffa/obj/KERNEL_OBJ ARCH=arm CROSS_COMPILE=arm-eabi- msm7627-perf_defconfig

out/target/product/msm7627_ffa/obj/KERNEL_OBJ/.config

CONFIG_MSM_N_WAY_SMSM=y

 

1.6 軟件調用流程分析

1.6.1 設置sim卡狀態

工程模式中顯

private void tryChangeSimLockState()

  Message callback = Message.obtain(mHandler, ENABLE_SIM_PIN_COMPLETE);

  mPhone.getSimCard().setSimLockEnabled(mToState, mPin, callback);

進入sim lock 菜單會顯示初始化pin狀態,是經過下面語句獲得:

mPinToggle.setChecked(mPhone.getSimCard().getSimLockEnabled());

 

mPhone.getSimCard().setSimLockEnabled(mToState, mPin, callback)調用的是文件:

GsmSimCard.java (frameworks\base\telephony\java\com\android\internal\telephony\gsm)中的函數:

public void setSimLockEnabled (boolean enabled,String password, Message onComplete) {

  int serviceClassX;

  serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +

                CommandsInterface.SERVICE_CLASS_DATA +

                CommandsInterface.SERVICE_CLASS_FAX;

  mDesiredPinLocked = enabled;

  phone.mCM.setFacilityLock(CommandsInterface.CB_FACILITY_BA_SIM,

                enabled, password, serviceClassX,

                obtainMessage(EVENT_CHANGE_FACILITY_LOCK_DONE, onComplete));

phone.mCM.setFacilityLock 調用的是文件:

RIL.java (frameworks\base\telephony\java\com\android\internal\telephony\gsm)中的函數:

    public void

    setFacilityLock (String facility, boolean lockState, String password,

                        int serviceClass, Message response)

    {

        String lockString;

         RILRequest rr

                = RILRequest.obtain(RIL_REQUEST_SET_FACILITY_LOCK, response);

        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));

        // count strings

        rr.mp.writeInt(4);

        rr.mp.writeString(facility);

        lockString = (lockState)?"1":"0";

        rr.mp.writeString(lockString);

        rr.mp.writeString(password);

        rr.mp.writeString(Integer.toString(serviceClass));

        send(rr);

    }

設置應用程序向 rild 發送 RIL_REQUEST_SET_FACILITY_LOCK 請求的 socket消息,

android的初始源代碼中 RIL_REQUEST_SET_FACILITY_LOCK 請求,在參考實現 Reference-ril.c

(hardware\ril\reference-ril) 中沒有實現。

咱們須要作得工做是:

vendor/qcom/proprietary/qcril/

vendor/qcom/proprietary/qcril/qcril_original/qcril_original.mk

LOCAL_MODULE:= libril-qc-1

LOCAL_PRELINK_MODULE := false

include $(BUILD_SHARED_LIBRARY)

device/qcom/msm7627_ffa/system.prop:5:

rild.libpath=/system/lib/libril-qc-1.so

 

./build/target/board/generic/system.prop

rild.libpath=/system/lib/libreference-ril.so

rild.libargs=-d /dev/ttyS0

 

 

 

 

 

 

1.6.2 設置背光

工程模式中顯示電池信息:

./hardware/msm7k/liblights/Android.mk:28:LOCAL_MODULE := lights.$(TARGET_BOARD_PLATFORM)

1.6.3 獲取電池信息

工程模式中顯示電池信息:

*#*#4636#*#* 進入android 自帶的工程模式

packages/apps/Settings/src/com/android/settings/BatteryInfo.java:88:

電壓發生變化就會收到 intent 爲 Intent.ACTION_BATTERY_CHANGED 的廣播消息:

action.equals(Intent.ACTION_BATTERY_CHANGED)

從intent 中獲取電壓值經過 TextView 來顯示

int plugType = intent.getIntExtra("plugged", 0);

mLevel.setText("" + intent.getIntExtra("level", 0));

mScale.setText("" + intent.getIntExtra("scale", 0));

mVoltage.setText("" + intent.getIntExtra("voltage", 0) + " "

                        + getString(R.string.battery_info_voltage_units));

int status = intent.getIntExtra("status", BatteryManager.BATTERY_STATUS_UNKNOWN);

 

./packages/apps/Settings/res/values-zh-rCN/strings.xml

<string name="battery_info_power_label" msgid="7465140230991349382">"是否已插電:"</string>

<string name="battery_info_status_label">"電池狀態:"</string>

<string name="battery_info_scale_label">"電池容量:"</string>

<string name="battery_info_level_label">"電池級別:"</string>

<string name="battery_info_voltage_label">"電池電壓:"</string>

mStatus.setText(statusString);

 

佈局文件 packages/apps/Settings/res/layout/battery_info.xml

id="@+id/status"   text="@string/battery_info_status_label"

id="@+id/power"    text="@string/battery_info_power_label"

id="@+id/level"    text="@string/battery_info_level_label"

id="@+id/scale"    text="@string/battery_info_scale_label"

id="@+id/voltage"  text="@string/battery_info_voltage_label"

 

電池狀態:

<string name="battery_info_status_charging_ac" >"(交流電)"</string>

<string name="battery_info_status_charging_usb" >"(USB 綁定選項)"</string>

<string name="battery_info_status_discharging" >"正在放電"</string>

<string name="battery_info_status_not_charging" >"未在充電"</string>

<string name="battery_info_status_full" >"已滿"</string>

 

電源狀態

switch (plugType) {

case 0:

//未插電

            mPower.setText(getString(R.string.battery_info_power_unplugged));

            break;

case BatteryManager.BATTERY_PLUGGED_AC:

        //交流電

            mPower.setText(getString(R.string.battery_info_power_ac));

            break;

case BatteryManager.BATTERY_PLUGGED_USB:

        //usb供電

            mPower.setText(getString(R.string.battery_info_power_usb));

            break;

case (BatteryManager.BATTERY_PLUGGED_AC|BatteryManager.BATTERY_PLUGGED_USB):

        // "交流電 + USB"

            mPower.setText(getString(R.string.battery_info_power_ac_usb));

            break;

default:

        // "未知"

            mPower.setText(getString(R.string.battery_info_power_unknown));

            break;

     }

 

關心電池信息的服務或者應用:

frameworks/base/services/java/com/android/server/PowerManagerService.java

frameworks/base/services/java/com/android/server/WifiService.java

frameworks/base/services/java/com/android/server/UiModeManagerService.java:324

frameworks/base/services/java/com/android/server/status/StatusBarPolicy.java

frameworks/base/services/java/com/android/server/NotificationManagerService.java

frameworks/base/services/java/com/android/server/NotificationManagerService.java

frameworks/base/tests/BatteryWaster/src/com/android/batterywaster/BatteryWaster.java

frameworks/base/tests/BatteryWaster/src/com/android/batterywaster/BatteryWaster.java

frameworks/policies/base/phone/com/android/internal/policy/impl/KeyguardUpdateMonitor.java

經過 filter.addAction(Intent.ACTION_BATTERY_CHANGED);

 

 

電池服務發送電池信息的 intent

frameworks/base/services/java/com/android/server/BatteryService.java

    private final void sendIntent() {

        //  Pack up the values and broadcast them to everyone

        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);

        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY

                | Intent.FLAG_RECEIVER_REPLACE_PENDING);

        try {

            mBatteryStats.setOnBattery(mPlugType == BATTERY_PLUGGED_NONE, mBatteryLevel);

        } catch (RemoteException e) {

            // Should never happen.

        }

 

        int icon = getIcon(mBatteryLevel);

 

        intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryStatus);

        intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryHealth);

        intent.putExtra(BatteryManager.EXTRA_PRESENT, mBatteryPresent);

        intent.putExtra(BatteryManager.EXTRA_LEVEL, mBatteryLevel);

        intent.putExtra(BatteryManager.EXTRA_SCALE, BATTERY_SCALE);

        intent.putExtra(BatteryManager.EXTRA_ICON_SMALL, icon);

        intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);

        intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mBatteryVoltage);

        intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mBatteryTemperature);

        intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryTechnology);

        。。。

        ActivityManagerNative.broadcastStickyIntent(intent, null);

    }

 

private synchronized final void update() {

    native_update();

    shutdownIfNoPower(); //點亮不足關機處理

    shutdownIfOverTemp();//溫度太高,關機處理

        。。。

        sendIntent();

        。。。

}

 

在電池服務啓動,或者有相關時間的時候會調用 update 獲得電池信息,而後經過廣播發出去

 private UEventObserver mUEventObserver = new UEventObserver() {

        @Override

        public void onUEvent(UEventObserver.UEvent event) {

            update();

        }

    };

根據jni調用規則,native_update 實際調用的是 android_server_BatteryService_update

frameworks/base/services/jni/com_android_server_BatteryService.cpp:226:

{"native_update", "()V", (void*)android_server_BatteryService_update},

 

#define POWER_SUPPLY_PATH "/sys/class/power_supply"

struct FieldIds {

    // members

    jfieldID mAcOnline;

    jfieldID mUsbOnline;

    jfieldID mBatteryStatus;

    jfieldID mBatteryHealth;

    jfieldID mBatteryPresent;

    jfieldID mBatteryLevel;

    jfieldID mBatteryVoltage;

    jfieldID mBatteryTemperature;

    jfieldID mBatteryTechnology;

};

 

static void android_server_BatteryService_update(JNIEnv* env, jobject obj)

{

    setBooleanField(env, obj, gPaths.acOnlinePath, gFieldIds.mAcOnline);

    setBooleanField(env, obj, gPaths.usbOnlinePath, gFieldIds.mUsbOnline);

    setBooleanField(env, obj, gPaths.batteryPresentPath, gFieldIds.mBatteryPresent);

   

    setIntField(env, obj, gPaths.batteryCapacityPath, gFieldIds.mBatteryLevel);

    setVoltageField(env, obj, gPaths.batteryVoltagePath, gFieldIds.mBatteryVoltage);

    setIntField(env, obj, gPaths.batteryTemperaturePath, gFieldIds.mBatteryTemperature);

   

    const int SIZE = 128;

    char buf[SIZE];

   

    if (readFromFile(gPaths.batteryStatusPath, buf, SIZE) > 0)

        env->SetIntField(obj, gFieldIds.mBatteryStatus, getBatteryStatus(buf));

    else

        env->SetIntField(obj, gFieldIds.mBatteryStatus,

                         gConstants.statusUnknown);

   

    if (readFromFile(gPaths.batteryHealthPath, buf, SIZE) > 0)

        env->SetIntField(obj, gFieldIds.mBatteryHealth, getBatteryHealth(buf));

 

    if (readFromFile(gPaths.batteryTechnologyPath, buf, SIZE) > 0)

        env->SetObjectField(obj, gFieldIds.mBatteryTechnology, env->NewStringUTF(buf));

}

 

cat /sys/class/power_supply/battery/type

cat /sys/class/power_supply/battery/status

cat /sys/class/power_supply/battery/health

cat /sys/class/power_supply/battery/present

cat /sys/class/power_supply/battery/technology

cat /sys/class/power_supply/battery/capacity

cat /sys/class/power_supply/battery/voltage_now

cat /sys/class/power_supply/battery/temp

cat /sys/class/power_supply/battery/current_now

cat /sys/class/power_supply/battery/current_avg

cat /sys/class/power_supply/battery/charge_counterBattery

$ Battery

$ Charging

$ Good

$ 1

$ Li-ion

$ 100

$ 4172644

$ 296

$ 85626

$ 86229

$ 1363200

驅動層具體實現(略)

 

 

1.7 python scons 語法學習

 

1.8 python  語法學習

1.8.1 Python中文全攻略

Python 絕對簡明手冊

http://wiki.woodpecker.org.cn/moin/PyAbsolutelyZipManual

Py標準庫手冊

http://wiki.woodpecker.org.cn/moin/PythonStandardLib

 

1.8.2 推薦一款Python編輯器

1.8.3 使用 pyExcelerator 讀 Execl 文件

首先從網站下載該軟件包

http://sourceforge.net/projects/pyexcelerator/

而後解壓縮,安裝

unzip pyexcelerator-0.6.4.1.zip

cd pyexcelerator-0.6.4.1/

python setup.py install

for example:

#!/usr/bin/env python

# -*- coding: UTF-8  -*-

from random import randint

from pyExcelerator import *

def test():

    print "aaa"

    w = Workbook() #建立一個工做簿

    ws = w.add_sheet('Hey, Hades') #建立一個工做表

    ws.write(0,0,'bit') #在1行1列寫入bit

    ws.write(0,1,'huang') #在1行2列寫入huang

    ws.write(1,0,'xuan') #在2行1列寫入xuan

    w.save('mini.xls') #保存

if __name__ == '__main__':

test()

 

1.8.4 xlrd 解析 xls 文件

sudo apt-get install python-xlrd

獲取有多少表單

book = xlrd.open_workbook(filename)

#打印sheet個數

Print book.nsheets

 

1.8.5 xlrd 生成 xls 文件

# # xlsBook = xlsApp.Workbooks.Open("c:\\magictong.xls") 

# # xlsSht = xlsBook.Worksheets("sheet1") 

#  

# xlsBook = xlsApp.Workbooks.Add() 

# xlsSht = xlsBook.Sheets.Add() 

# xlsSht.Cells(2, 3).Value = "Tecent QQ" 

# xlsSht.Cells(2, 3).Font.Color = 0xff0000 

#  

# xlsSht.Name = "GCD go to bell" 

# xlsBook.SaveAs("c:\\magictong.xls") 

# xlsApp.Quit() 

 

1.9 Python 語言之 scons 工具流程分析

 

高通的modem代碼中自帶了 scons 工具,無需本身安裝。

若是本身安裝 scons 執行腳本

setup.py

class install_lib(_install_lib):

    ....

self.install_dir = '/usr/local/lib'

 

script/scons 文件的最後有:

if __name__ == "__main__":

    import SCons.Script

    # this does all the work, and calls sys.exit

    # with the proper exit status when done.

    SCons.Script.main()

代表該文件是腳本,而不是模塊。

========================

由於 Python 腳本和模塊都是一個以.py結束的文件,那程序是如何判斷一個.py文件是做爲腳本仍是模塊呢?

關鍵是一個名爲__name__的變量,若是它的值是__main__,則不能做爲模塊,只能做爲腳本直接運行。因此

在不少腳本的最後都有一段相似下面的語句,限制只能以腳本方式運行,不做爲模塊:

if __name__ == '__main__':

    main()

=========================

SCons.Script.main()實際上執行的是文件:

/usr/local/lib/scons-1.2.0/SCons/Script/Main.py

 

在 def _main(parser): 函數中有:

    ...

    scripts = []

    if options.file:

        scripts.extend(options.file)

    if not scripts:

        sfile = _SConstruct_exists(repositories=options.repository,

                                   filelist=options.file)

        if sfile:

            scripts.append(sfile)

 

    if not scripts:

        if options.help:

            # There's no SConstruct, but they specified -h.

            # Give them the options usage now, before we fail

            # trying to read a non-existent SConstruct file.

            raise SConsPrintHelpException

        raise SCons.Errors.UserError, "No SConstruct file found."

    ...

 

scons --help 答應幫助信息

執行 scons 命令,那麼經過函數 _SConstruct_exists 會在當前目錄下查找名爲 SConstruct 的文件,若是

不存在,那麼 sfile 等於 None, 若是存在 sfile 等於 SConstruct

若是 scons -f makefile 指定腳本文件,那麼 options.file 等於 ['makefile']

scripts = [] 通過 scripts.extend(options.file) 處理之後變爲: ['makefile']

 

默認狀況下 options 的值爲:

{'debug_explain': False, 'debug_includes': False, '__defaults__': <Values at 0xa20652c: {'implicit_cache': False, 'cache_debug': None, 'cache_force': False, 'keep_going': False, 'random': False, 'no_builtin_rules': None, 'list_actions': None, 'list_where': None, 'no_exec': False, 'directory': [], 'file': [], 'warn_undefined_variables': None, 'help': False, 'old_file': [], 'md5_chunksize': 64, 'silent': False, 'question': False, 'duplicate': 'hard-soft-copy', 'write_filenames': None, 'override': None, 'implicit_deps_unchanged': False, 'config': 'auto', 'no_progress': False, 'stack_size': None, 'load_average': 0, 'climb_up': 0, 'cache_disable': False, 'new_file': None, 'site_dir': None, 'max_drift': 172800, 'warn': [], 'tree_printers': [], 'taskmastertrace_file': None, 'ignore_errors': False, 'cache_show': False, 'profile_file': None, 'include_dir': [], 'diskcheck': None, 'repository': [], 'p': None, 'list_derived': None, 'clean': False, 'debug': [], 'no_site_dir': False, 'num_jobs': 1, 'implicit_deps_changed': False, 'interactive': False}>, '__SConscript_settings__': {}}

 

 

開始編譯:

    ...

    taskmaster = SCons.Taskmaster.Taskmaster(nodes, task_class, order, tmtrace)

    ...

    global num_jobs

    num_jobs = options.num_jobs

    jobs = SCons.Job.Jobs(num_jobs, taskmaster)

    ...

    def jobs_postfunc(

        jobs=jobs,

        options=options,

        closing_message=closing_message,

        failure_message=failure_message

        ):

        if jobs.were_interrupted():

            progress_display("scons: Build interrupted.")

            global exit_status

            global this_build_status

            exit_status = 2

            this_build_status = 2

 

        if this_build_status:

            progress_display("scons: " + failure_message)

        else:

            progress_display("scons: " + closing_message)

        if not options.no_exec:

            if jobs.were_interrupted():

                progress_display("scons: writing .sconsign file.")

            SCons.SConsign.write()

 

    progress_display("scons: " + opening_message)

    jobs.run(postfunc = jobs_postfunc)

....

 

jobs.run 執行的是文件:

/usr/local/lib/scons-1.2.0/SCons/Job.py 中類 Jobs 的 run 函數:

 

 

Jobs 類分析:

class Jobs:

    # 一個類的實例能夠初始化多個jobs,它提供了 啓動,中止,等待 這些jobs 的方法。

    def __init__(self, num, taskmaster):

        #若是 num 等於或者小於 1, 使用串行的工做方式,不然全部的工做線程將並行運行

        屬性 'num_jobs' 設置成實際的jobs數,若是 job 的請求數大於 1 ,可是 並行工做沒法執行,

    那麼 'num_jobs' 將會被重置爲 1 . 初始化以後,Wrapping interfaces that

        care 將會對 'num_jobs' 值進行檢測。

 

        self.job = None

        if num > 1:

            stack_size = explicit_stack_size

            if stack_size is None:

                stack_size = default_stack_size

               

            try:

                self.job = Parallel(taskmaster, num, stack_size)

                self.num_jobs = num

            except NameError:

                pass

        if self.job is None:

            self.job = Serial(taskmaster)

            self.num_jobs = 1

 

    def run(self, postfunc=lambda: None):

        self._setup_sig_handler()

        try:

            self.job.start()

        finally:

            postfunc()

            self._reset_sig_handler()

 

    def were_interrupted(self):

        Returns whether the jobs were interrupted by a signal.

        return self.job.interrupted()

 

    def _setup_sig_handler(self):

 

        def handler(signum, stack, self=self, parentpid=os.getpid()):

            if os.getpid() == parentpid:

                self.job.taskmaster.stop()

                self.job.interrupted.set()

            else:

                os._exit(2)

 

        self.old_sigint  = signal.signal(signal.SIGINT, handler)

        self.old_sigterm = signal.signal(signal.SIGTERM, handler)

        try:

            self.old_sighup = signal.signal(signal.SIGHUP, handler)

        except AttributeError:

            pass

 

    def _reset_sig_handler(self):

        """Restore the signal handlers to their previous state (before the

         call to _setup_sig_handler()."""

 

        signal.signal(signal.SIGINT, self.old_sigint)

        signal.signal(signal.SIGTERM, self.old_sigterm)

        try:

            signal.signal(signal.SIGHUP, self.old_sighup)

        except AttributeError:

            pass

 

Scons 全局經常使用方法:

# The list of global functions to add to the SConscript name space

# that end up calling corresponding methods or Builders in the

# DefaultEnvironment().

GlobalDefaultEnvironmentFunctions = [

    # Methods from the SConsEnvironment class, above.

    'Default',

    'EnsurePythonVersion',

    'EnsureSConsVersion',

    'Exit',

    'Export',

    'GetLaunchDir',

    'Help',

    'Import',

    #'SConscript', is handled separately, below.

    'SConscriptChdir',

 

    # Methods from the Environment.Base class.

    'AddPostAction',

    'AddPreAction',

    'Alias',

    'AlwaysBuild',

    'BuildDir',

    'CacheDir',

    'Clean',

    #The Command() method is handled separately, below.

    'Decider',

    'Depends',

    'Dir',

    'NoClean',

    'NoCache',

    'Entry',

    'Execute',

    'File',

    'FindFile',

    'FindInstalledFiles',

    'FindSourceFiles',

    'Flatten',

    'GetBuildPath',

    'Glob',

    'Ignore',

    'Install',

    'InstallAs',

    'Literal',

    'Local',

    'ParseDepends',

    'Precious',

    'Repository',

    'Requires',

    'SConsignFile',

    'SideEffect',

    'SourceCode',

    'SourceSignatures',

    'Split',

    'Tag',

    'TargetSignatures',

    'Value',

    'VariantDir',

]

GlobalDefaultBuilders = [

    # Supported builders.

    'CFile',

    'CXXFile',

    'DVI',

    'Jar',

    'Java',

    'JavaH',

    'Library',

    'M4',

    'MSVSProject',

    'Object',

    'PCH',

    'PDF',

    'PostScript',

    'Program',

    'RES',

    'RMIC',

    'SharedLibrary',

    'SharedObject',

    'StaticLibrary',

    'StaticObject',

    'Tar',

    'TypeLibrary',

    'Zip',

    'Package',

]

 

for name in GlobalDefaultEnvironmentFunctions + GlobalDefaultBuilders:

    exec "%s = _SConscript.DefaultEnvironmentCall(%s)" % (name, repr(name))

del name

1.9.1 Program 方法

編譯可執行程序

1.9.2 Library 方法

Scons能夠用env.Library(‘liba’, ‘a.c’)的方法用環境的定義編譯靜態庫,或者用Program定義可執行程序。而且支持輸入和環境定義不一樣的參數,如

env.Library(‘liba’, ‘a.c’, CPPDEFINES = ['NEWMACRO'], CCFLAGS=['/Ox'])。

不過,很惋惜,Builder默認是覆蓋環境中現有參數,而不是追加。因此,要用多個編譯參數稍有不一樣的程序和庫編譯只能用Clone後Append。

tempEnv = libEnv.Clone()

tempEnv.Append(CPPDEFINES = ['NEWMACRO'], CCFLAGS=['/Ox'])

tempEnv.Library('liba', 'a.c')

最近用scons的收穫

http://blog.chinaunix.net/u2/71769/showart_2243166.html

 

二、高一般用工具使用

2.1 QPST

QPST(Qualcomm Product Support Tool),這個工具相似電腦上的資源管理器,可用於手機和PC間的數據傳輸,手機軟件版本升級,部份內置參數如 APN的修改,上行加密,完整性保護參數設置等。

2.2 QXDM

QXDM(Qualcomm eXtensive Diagnostic Monitor),主要用於抓取up口的上,下行信令業務數據包,並可多窗口實時顯示諸如功率,速率,誤碼率等參數,是系統測試人員最經常使用的軟件之一。

經常使用功能

2.3 QCAT

QCAT(Qualcomm log Analysis Tool) ,它主要用於對 QXDM捕獲的二進制代碼文件進行解碼分析,並可轉換爲文本格式輸出。APEX(Analysis and Post-processing Expert)是QCAT的升級替換版本,功能是相似的。

 

三、工程模式

Making a Factory Image

1. To make a factory image, the file mibib.mbn must exist in the

   \build\ms\bin\<build_id> directory.

2. To verify the factory image with USB, the file \tools\mjnand.cmm must include

   the option 「Program Factory Image」.

有誰用過QSC6085平臺採用NAND FLASH燒錄,具體怎麼打包燒錄文件?還有想把文件系統也打包到燒錄文件裏怎麼實現?請高手不嗇賜教!!!小弟在此謝過!!!!

用tools目錄下的qfit生成,有文檔介紹的。多看看資料。。。。。。。

 

./AMSS/products/7x30/build/ms/dmss_rules.min

genmibib:

    @echo ----------------------------------------------------------------------

    @echo Building mibib.mbn

    @pwd

    #$(BUILD_MIBIB_CMD)

    @echo ----------------------------------------------------------------------

BUILD_MIBIB_CMD 在文件 ./AMSS/products/7x30/build/ms/armtools.min:333 中

ifeq ($(BUILD_UNIX), yes)

ac_EXE=

else

ac_EXE=.exe

endif

BUILD_MIBIB_CMD = $(FLASH_NAND_TOOLS_SRC)/nand_tools$(ac_EXE) -fp $(NAND_PAGE_SIZE) -fb $(NAND_BLK_SIZE) -fd $(NAND_DEVICE_SIZE) \

                  -u partition.mbn -q qcsblhd_cfgdata.mbn -ah amsshd.mbn -m mibib.mbn -oh oemsblhd.mbn \

                  -wh appshd.mbn -bh appsboothd.mbn -p $(MIBIB_DEST_PATH)

把 genmibib 規則中的 #$(BUILD_MIBIB_CMD) 選項打開

它其實是進入目錄: AMSS/products/7x30/build/ms  而後執行命令:

../../core/storage/flash/tools/src/nand/nand_tools -fp 4096 -fb 64 -fd 1024 -u partition.mbn -q qcsblhd_cfgdata.mbn -ah amsshd.mbn -m mibib.mbn -oh oemsblhd.mbn -wh appshd.mbn -bh appsboothd.mbn -p ../../build/ms/bin/AABBQOLY

要生成 qcsblhd_cfgdata.mbn  還必須打開文件

./AMSS/products/7x30/build/ms/dmss7X30modem.mak:49 中的

#include boot_targets_$(SEC_MODE).min 語句

 

. ./make-AAABQOLYM.sh  gencfgdata

Generating Configuration Generation Tool

make: *** ../../secboot/cfg_data: 沒有該文件或目錄。 中止。

make: *** [../../secboot/cfg_data/Config_Gen.exe] 錯誤 2

. ./make-AAABQOLYM.sh  genmibib

. ./make-AAABQOLYM.sh  gencfgdata

 

從目前的版本中能夠看出,只有文件 partition.mbn 存在,其餘都不存在。Oemsblhd.mbn 等這些只存在老的軟件版本中。

 

運行 QFIT 工具

Perl 工具 /opt/shared/win_exe/ActivePerl-5.6.1.638-MSWin32-x86.msi

Windows dos 窗口下,進入 qfit 目錄執行 QFIT.cmd 啓動 qfit程序

 

./AMSS/products/7x30/core/bsp/build/data/incpathsaaabqmazm.py:472:  

env.Replace(FLASH_NAND_TOOLS_CFG = "config_v2")

./AMSS/products/7x30/core/bsp/build/data/incpathsaabbqclym.py:166:  

env.Replace(FLASH_HAL_CFG = "config_v2")

 

HAL  headware abstract layer

DAL

./AMSS/products/7x30/build/ms/bin/AABBQOLY/NPRG7x30.hex

./AMSS/products/7x30/core/bsp/tools/flash/hostdl/build/NPRG7x30_AABBQOLYM.hex

 

QFIT工具的位置

./AMSS/products/7x30/tools/qfit

qfit 工具只能在 windows 環境下使用,經過 QFIT.cmd 腳本啓動 QFIT 工具

運行 QFIT.cmd 腳本以前設置環境變量:set PERL5.6.1=c:\perl\bin

qfit.pl ->

use Make_Factory_Image;

Make_Factory_Image::make_factory_image

 

生成 Factory Image

./AMSS/products/7x30/tools/qfit/QFIT.pl:1108:

make_frame('MakeFactoryImage','$tab21');

$show_layout_button = make_button("Preview\n Image Layout",$action_no_target_color,'&preview_image_layout');

$MakeFactoryButton  = make_button("Make\nFactory Image",$action_no_target_color,'&make_factory_image');

make_frame('MakeFactoryImage2','$tab21');

make_button("Select Image  \nFile",$action_not_configured_color,'&SelectFactoryFile');

make_entry_box('','$FactoryImageFileName',$file_box_size);

make_frame('MakeFactoryImage3','$tab21');

make_progress_bar('\$factory_make_percent');

 

Make_Factory_Image::make_factory_image({

                                 factory_image_file      => $FactoryImageFileName,

                                 include_partitions_ref  => \@image_include,

                                 single_partition_file   => $make_factory_image_single_partition_output_file,

                                 partition_mbn_file      => $partition_mbn_file,

                                 local_directory         => $LocalDir,

                                 include_factory_header  => $include_factory_header,

                                 make_dataio_files       => $make_dataio_files,

                                 reuse_ecc_file          => $reuse_ecc_file,

                                 abort_after_error       => $abort_after_error,

                                 percent_done_ref        => \$factory_make_percent,

                           });

Make_Factory_Image::make_factory_image 執行的是文件:

./AMSS/products/7x30/tools/qfit/Make_Factory_Image.pm:

中的函數 make_factory_image

AMSS build must contain mibib.mbn to use QFIT 1.5.02

同時須要的有:

mibib.mbn amss.mbn appsboot.mbn apps.mbn

經過 QFIT 生成 factory image 必須存在 mibib.mbn

 

燒寫 Factory Image 經過 qpst

make_frame('ProgramFactoryImage','$tab22');

$ProgramButton = make_button("Program Factory\nImage into Phone",$action_qpst_target_color,'&program_factory_image_qpst');

 

$ProgramFactoryImage_fr->Label(-text=>'   Factory image is programmed into phone using QPST') -> pack( -side => 'left');

make_frame('ProgramFactoryImage2','$tab22');

make_button("    Select Image    \nFile",$action_not_configured_color,'&SelectProgramFile');

make_entry_box('','$ImageProgramFileName',$file_box_size);

 

sub program_factory_image_qpst

exec ("perl Program_Factory_Image.pl $com_port $timeout $factory_file");

 

 

 

 

四、Android 系統更新升級總結

4.1 刷機基本知識

1. 恢復模式,用update.zip文件

2. 工程模式刷機,刷NBH文件(官方版本)

3. fastboot模式刷機(燒寫img文件)

 

第一種,這也是最經常使用的刷機方式。  首先,須要有testkey和ROOT,由於絕大部分的update.zip文件都是自制的,須要有足夠的權限,才能使用測試簽名的文件。將ROM 放進SD,並更名爲update.zip,關機,按特定的鍵開機進入恢復模式。不一樣廠商的手機進入恢復模式的方法會不同。

 

第二種,一般刷官方發佈的NBH文件,刷完會失去ROOT。 NBH文件對應地區,若是沒有開發版的工程模式,只能刷與你手機地區對應的NBH文件。要刷NBH,首先格式化SD卡,選擇FAT32格式。  放入NBH文件,更名成DreaIMG.NBH,NBH是擴展名。 接着關機,按特定的鍵進入工程模式,加載完成後,按關機鍵,開始加載NBH文件,期間5-10分鐘,不用管,完成後,按任意鍵,而後特定鍵關機,重啓進入系統。

 

第三種,fastboot 模式刷機咱們應該比較熟悉,在咱們軟件開發階段,咱們就是用這種方法來燒寫軟件的,它的原理是直接擦出、燒寫、替換分區。  手機端須要SPL支持,這裏的SPL就是咱們一般所說的 appsboot.mbn , 這個文件來來自android 源代碼,編譯後一般生成爲:

out/target/product/msm7630_surf/appsboot.mbn 他的源代碼在:

android/bootable/bootloader/lk/

PC端有fastboot命令與手機端的 fastboot 進行通訊,傳入特定的命令,讓手機端完成分區擦出、燒寫、重啓等任務。原理和具體使用方法參考 fastboot 刷機

 

目前咱們已經能作到第一和第三種的刷機方式,第二種由於原理還不是很明白,會根據實際狀況再介紹。

 

4.1.1 各品牌表明手機刷機模式進入方法

4.1.1.1 HTC G1

Home+電源  進入recovery模式

電源+照相  進入工程模式

回鍵+電源  進入fastboot模式

4.1.1.2 三星 Galaxy i7500 

專用刷機模式  進入方法:音量向下+OK+電源

recovery模式  進入方法:音量向下+通話+電源

Fastboot模式,進入方法:通話+電源

也就是看SPL版本那個畫面

4.1.1.3 Google Nexus One

Fastboot 模式  進入方法:"電源鍵+軌跡球"

進入 fastboot 模式後,能夠經過音量鍵和電源鍵在 recovery 、hboot、fastboot 集中模式間進行切換。

4.1.2 fastboot 模式

4.1.2.1 fastboot 模式概述

Fastboot 和 HBoot 模式在 appsboot.mbn 中

 

終端執行如下命令 sudo fastboot devices ,若是設備鏈接正常且進入fastboot 模式那麼會返回相似以下的信息:

HT849GZ58999  fastboot

Fastboot pc客戶端和手機端一般須要版本一致或者接近,不然會出現找不到設備,或者某些命令沒法支持。

除了按鍵能進入 fastboot 模式外,系統重啓也能夠進入。

reboot_device(FASTBOOT_MODE);

./bootloader/lk/app/aboot/aboot.c:59:#define FASTBOOT_MODE   0x77665500

./bootloader/lk/target/msm7630_surf/init.c:251:

void reboot_device(unsigned reboot_reason)

    reboot(reboot_reason);

./bootloader/lk/platform/msm_shared/proc_comm.c:243:

void reboot(unsigned reboot_reason)

 

void reboot(unsigned reboot_reason)

{

        msm_proc_comm(PCOM_RESET_CHIP, &reboot_reason, 0);

        for (;;) ;

}

 

內核中的重啓:

void machine_restart(char * __unused)

{

        arm_pm_restart(reboot_mode);

}

./kernel/kernel/sys.c:308:  machine_restart(cmd);

 

void kernel_restart(char *cmd)

{

    kernel_restart_prepare(cmd);

    if (!cmd)

       printk(KERN_EMERG "Restarting system.\n");

    else

       printk(KERN_EMERG "Restarting system with command '%s'.\n", cmd);

    machine_restart(cmd);

}

./kernel/kernel/sys.c:414:     

kernel_restart(buffer);

 

kernel/arch/alpha/kernel/process.c:102:  

if (how->mode == LINUX_REBOOT_CMD_RESTART) {

kernel/arch/alpha/kernel/process.c:146:  

if (! alpha_using_srm && how->mode != LINUX_REBOOT_CMD_RESTART) {

kernel/arch/alpha/kernel/process.c:171:  

common_shutdown(LINUX_REBOOT_CMD_RESTART, restart_cmd);

4.1.2.2 PC端fastboot 命令分析

4.1.2.2.1 命令選項 –w –s  -p –c

sudo fastboot –w

將會擦除 userdata  和 cache  分區

erasing 'userdata'... OKAY

erasing 'cache'... OKAY

若是設備未就緒提示:

< waiting for device >

 

sudo fastboot boot –s

sudo fastboot -s WH9AMP200206 getvar version

返回:

sudo fastboot -s WH9AMP200206 getvar product

返回:

 

usb_handle *usb_open(ifc_match_func callback)

{

    return find_usb_device("/dev/bus/usb", callback);

}

./system/core/fastboot/usb_linux.c

經過讀取設備文件 /dev/bus/usb/

咱們的大板插入usb 進入 fastboot 模式,會有設備:

/dev/bus/usb/001/022

若是咱們設備的驅動中沒有指定,那麼將顯示 '???????'

 

sudo fastboot boot –c xxxx

-c 用於啓動內核的時候指定命令行參數,覆蓋內核的命令行參數

 

jresult_t core_handle_ep0(void *core_ctx, juint8_t *buffer, device_speed_t speed)

./AMSS/products/7x30/core/wiredconnectivity/hsusb/core/src/jslave/core/jusb_core.c:1060:   

return chp9_handle_usb_command(core, buffer, core->ep0_req_tag);

chp9_handle_usb_command調用的是文件:

./AMSS/products/7x30/core/wiredconnectivity/hsusb/core/src/jslave/core/jusb_chp9.c:2057 中的函數:

jresult_t chp9_handle_usb_command(core_t *core, void *buffer, juint8_t ep0_req_tag)

if (req_type == USB_TYPE_STANDARD)

{

rc = core_usb_command(core, ctrl_req, ep0_req_tag);

if (rc != JENOTSUP)

goto Exit;

}

case USB_REQ_GET_DESCRIPTOR:

DBG_V(DSLAVE_CORE, ("CH9: Get descriptor request reached core\n"));

rc = handle_get_descriptor(core, wValue, wIndex, wLength, ep0_req_tag);

break;

 

static jresult_t handle_get_descriptor(core_t *core, juint16_t wValue,

    juint16_t wIndex, juint16_t wLength, juint8_t ep0_req_tag)

    case USB_DT_DEVICE:

        rc = send_descriptor_device(core, wLength, ep0_req_tag);

        break;

 

static jresult_t send_descriptor_device(core_t *core, juint16_t wLength,

    juint8_t ep0_req_tag)

....

    device_desc.iProduct = core->i_product;

    device_desc.iManufacturer = core->i_manufacturer;

    device_desc.iSerialNumber = core->i_serial_number;

    device_desc.idVendor        = htole16(dev_info->vendor);

    device_desc.idProduct       = htole16(dev_info->product);

 

 

4.1.2.3 手機端fastboot 命令分析

fastboot_register("boot", cmd_boot);

fastboot_register("erase:", cmd_erase);

fastboot_register("flash:", cmd_flash);

fastboot_register("continue", cmd_continue);

fastboot_register("reboot", cmd_reboot);

fastboot_register("reboot-bootloader", cmd_reboot_bootloader);

fastboot_register("getvar:", cmd_getvar);

fastboot_register("download:", cmd_download);

4.1.2.3.1 boot

4.1.2.3.2 erase

4.1.2.3.3 flash

4.1.2.3.4 continue

4.1.2.3.5 reboot

4.1.2.3.6 reboot-bootloader

4.1.2.3.7 getvar

bootable/bootloader/lk/app/aboot/aboot.c

fastboot_publish("product", "swordfish");

fastboot_publish("kernel", "lk");

fastboot_publish("version", "0.5");

調用

sudo fastboot  getvar product

sudo fastboot  getvar kernel

sudo fastboot  getvar lk

只有 fastboot_publish 某變量之後,才能用 sudo fastboot  getvar 獲取某變量的值

4.1.2.3.8 download

dd  

4.1.2.3.9 update

4.1.2.3.9.1 system/core/fastboot/fastboot.c:294:       

4.1.2.3.9.2 fprintf(stderr, "archive does not contain '%s'\n", name);

4.1.2.4 fastboot 模式流程分析

 

4.1.3 recovery 模式

4.1.3.1 recovery 模式概述

Recovery 模式是 android 手機進行系統恢復/升級的一種方式,在設置模塊中經過菜單 」恢復出廠設置」把系統能恢復到出廠默認狀態(會清空用戶保存在手機上的電話本,短信,電子郵件,應用程序數據等信息);經過按鍵進入該模式能夠把 sdcard 上的系統升級包寫入到手機中實現系統軟件更新。

進入 recovery 模式須要必定條件,一般如下幾種方式能夠進入:

1. 關機狀態下經過按鍵進入(如:同時按 HOME + 電源 進入 recovery 模式)

2. 恢復出廠設置進入 recovery 模式

3. 系統升級進入 recovery 模式

4. 開機狀態下經過重啓進入

 

進入 recovery 分區的前提是:

手機必須存在 recovery 分區,而且燒寫了 recovery.img 鏡像文件。

recovery.img 鏡像文件主要包括兩部分:

1. 標準的內核鏡像 out/target/product/msm7630_surf/kernel

2. 一個小的文件系統 out/target/product/msm7630_surf/ramdisk-recovery.img,這個小系統提供了一套字符 ui 程序,用於與用戶的交互。

 

相對於正常啓動的 ramdisk.img ,ramdisk-recovery.img 主要有以下區別:

1. init.rc 的內容進行了簡化,原始文件爲:bootable/recovery/etc/init.rc

2. sbin 目錄下多了可執行程序 /sbin/recovery  源代碼爲: bootable/recovery

3. 根目錄下多了 res 資源文件夾, 原始文件爲 bootable/recovery/res

4. 資源文件夾下有 res/keys 文件,用於軟件安裝時候的文件驗證

5. 根目錄下文件 default.prop 的內容分別來自:

out/target/product/msm7630_surf/root/default.prop out/target/product/msm7630_surf/system/build.prop

 

系統升級能夠經過多種方式進行:

1. 手機開機狀態下,經過手機自帶的升級程序鏈接指定的網站下載特定的通過認證的軟件包進行升級,此種升級方式一般是官方自帶的,軟件包也是官方(手機軟件提供商)提供。

2. 經過按鍵進入 手機的 recovery 模式,把待升級的軟件包放在手機SD卡的根目錄,而後選擇 recovery的相應菜單進行升級。此中升級方式在 android 的破解版中很流行,目前安卓網等論壇提供的 android 手機刷機方法都推薦這種方法。

 

無論是主動仍是被動進入 recovery 模式,其目的都是爲了給手機軟件升級或者恢復系統的默認設置,若是是升級系統,那麼咱們就得製做升級包。

 

4.1.3.2 軟件升級包

可以被Recovery程序識別並處理的軟件升級包一般包括一些特有的規則:

1)必須是標準的zip壓縮包;

2)recovery腳本必須存入在META-INF\com\google\android\update-script;

3)其它的一些證書和簽名信息應該都放在\META-INF\下。

 

升級通常經過運行升級包中的META-INF/com/google/android/update-script腳原本執行自定義升級,腳本中是一組recovery 系統能識別的控制命令,文件系統操做命令,例如write_raw_image(寫FLASH分區),copy_dir(複製目錄)。該包通常被下載至SDCARD

不一樣版本的 recovery 程序,它的 update-script 命令格式是不同的,例如:

Cupcake 的recovery 程序支持 copy_dir 命令,1.6之後的版本已經取消。

 

4.1.3.3 recovery v1跟recovery v2的區別

recovery v2是從donut開始出現的, 相對於recovery v1作了很多的改動,加強了原有的功能的同時,儘可能將可能變化的部分隔離出來,讓各廠商能夠添加本身的特性,這些體如今UI,設備功能上。 下面是從v1到v2改動的地方:

一、ui部分獨立出來放到default_recovery_ui.c

界面上的修改通常改這裏就能夠了。

 

二、腳本解析器從amend切換到edify

edify支持簡單的邏輯語法,腳本語法也不兼容了,不要迷戀recovery/etc/META-INF/com/google/android/update-script,這個腳本已經

不適合recovery v2。

 

4.1.3.4 軟件升級腳本語法解析

eclair 版本的 recovery 程序支持如下腳本控制命令:

./bootable/recovery/updater/install.c   

RegisterFunction("mount", MountFn);

RegisterFunction("is_mounted", IsMountedFn);

RegisterFunction("unmount", UnmountFn);

RegisterFunction("format", FormatFn);

RegisterFunction("show_progress", ShowProgressFn);

RegisterFunction("set_progress", SetProgressFn);

RegisterFunction("delete", DeleteFn);

RegisterFunction("delete_recursive", DeleteFn);

RegisterFunction("package_extract_dir", PackageExtractDirFn);

RegisterFunction("package_extract_file", PackageExtractFileFn);

RegisterFunction("symlink", SymlinkFn);

RegisterFunction("set_perm", SetPermFn);

RegisterFunction("set_perm_recursive", SetPermFn);

RegisterFunction("getprop", GetPropFn);

RegisterFunction("file_getprop", FileGetPropFn);

RegisterFunction("write_raw_image", WriteRawImageFn);

RegisterFunction("write_firmware_image", WriteFirmwareImageFn);

RegisterFunction("apply_patch", ApplyPatchFn);

RegisterFunction("apply_patch_check", ApplyPatchFn);

RegisterFunction("apply_patch_space", ApplyPatchFn);

RegisterFunction("ui_print", UIPrintFn);

RegisterFunction("run_program", RunProgramFn);

 

./bootable/recovery/edify/expr.c:   

RegisterFunction("ifelse", IfElseFn);

RegisterFunction("abort", AbortFn);

RegisterFunction("assert", AssertFn);

RegisterFunction("concat", ConcatFn);

RegisterFunction("is_substring", SubstringFn);

RegisterFunction("stdout", StdoutFn);

RegisterFunction("sleep", SleepFn);

RegisterFunction("less_than_int", LessThanIntFn);

RegisterFunction("greater_than_int", GreaterThanIntFn);

RegisterFunction(const char* name, Function fn);

 

4.1.3.4.1.1 mount

mount 命令解析

高通 7630 分區信息:

$ cat /proc/mtd

dev:    size   erasesize  name

mtd0: 00500000 00040000 "boot"

mtd1: 06900000 00040000 "system"

mtd2: 00500000 00040000 "cache"

mtd3: 13480000 00040000 "userdata"

mtd4: 00300000 00040000 "persist"

mtd5: 00500000 00040000 "recovery"

語法爲:Mount(type, location, mount_point)

若是 type 爲 "MTD", 那麼 location 能夠爲設備分區名稱,默認該分區以 "yaffs" 的方式掛載,如掛載 system 分區:

mount("MTD", "system", "/system")

若是 type 不爲 "MTD" ,那麼必須寫明具體的文件系統類型, location 必須填設備名稱,例如是sdcard ,那麼 type 爲 "vfat"  設備名稱 /dev/block/mmcblk0 :

mount("vfat","/dev/block/mmcblk0","sdcard")

 

 

system 分區掛載過程:

mount("MTD", "system", "/system")

mkdir("system", 0755);

mtd = mtd_find_partition_by_name("system");

mtd_mount_partition(mtd, "/system", "yaffs2", 0 /* rw */)

const unsigned long flags = MS_NOATIME | MS_NODEV | MS_NODIRATIME;

sprintf(devname, "/dev/block/mtdblock%d", mtd->device_index);

mount(/dev/block/mtdblock, "/system", "yaffs2" , flags, NULL);

若是 mtd_mount_partition 第四個參數不爲 0,那麼以只讀方式掛載:

mount(devname, mount_point, filesystem, flags | MS_RDONLY, 0)

平時沒法寫系統分區,是由於 init 在讀取 init.rc 後,默認掛載system 爲只讀

系統更新能夠寫system分區,是由於這裏把該分區掛載成了可讀寫

 

sdcard 掛載過程:

mount("vfat","/dev/block/mmcblk0","sdcard")

mkdir("system", 0755);

mount("/dev/block/mmcblk0", "/sdcard", "vfat",MS_NOATIME | MS_NODEV | MS_NODIRATIME, "")

 

4.1.3.4.1.2 getprop

從系統環境中獲取屬性值

如:

 

4.1.3.4.1.3 file_getprop

語法:

從屬性文件中獲取屬性值,能夠爲android系統中的任意屬性配置文件

例如:

getprop ro.bootloader

 

4.1.3.4.1.4 assert

語法:

此命令至關於程序中的斷言

RegisterFunction("assert", AssertFn); 它執行的是 AssertFn 函數

assert() 函數用法

assert宏的原型定義在<assert.h>中,其做用是若是它的條件返回錯誤,則終止程序執行。

4.1.3.4.1.5 format

格式化分區

format BOOT:

format SYSTEM:

4.1.3.4.1.6 apply_patch_check

4.1.3.4.1.7 apply_patch_space

4.1.3.4.1.8 apply_patch

apply_patch_check 

apply_patch_space

apply_patch

以上命令在手機端都是執行函數 ApplyPatchFn

./bootable/recovery/updater/install.c

RegisterFunction("apply_patch", ApplyPatchFn);

RegisterFunction("apply_patch_check", ApplyPatchFn);

RegisterFunction("apply_patch_space", ApplyPatchFn);

語法:

apply_patch(srcfile, tgtfile, tgtsha1, tgtsize, sha1:patch, ...)

apply_patch_check(file, sha1, ...)

apply_patch_space(bytes)

 

apply_patch_check

對升級包進行驗證,patch 包是否正確,若是不正確,異常退出

例如:

assert(apply_patch_check("/system/app/Settings.apk", "682e475c6411bb454d5999f6abff50ca8eb373f4", "196c0891869ec4b93a738519daf30a56a96c570d"));

 

apply_patch_space

檢查可用的存儲空間

bootable/recovery/updater/install.c:

char* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[])

 

對軟件包進行打patch

apply_patch("/system/app/Settings.apk", "-",

            682e475c6411bb454d5999f6abff50ca8eb373f4, 1485651,

            "196c0891869ec4b93a738519daf30a56a96c570d:/tmp/patchtmp/system/app/Settings.apk.p");

4.1.3.4.1.9 package_extract_file

pac

package_extract_file("system/app/Settings.apk", "/system/app/ Settings.apk");

4.1.3.4.1.10 ui_print

語法:

ui_print("Verifying current system...");

在屏幕上打印信息: 正在驗證當前系統...

4.1.3.4.1.11 META-INF/com/google/android/update-script 腳本分析

下面以一個升級包的實例分析系統升級具體作了些什麼?

=========================

由於要更新系統內容,因此首先掛載系統分區爲可讀寫

mount("MTD", "system", "/system");

檢測屬性文件 /system/build.prop 中的屬性值

assert(file_getprop("/system/build.prop", "ro.build.fingerprint") == "google/passion/passion/mahimahi:2.1/ERD79/22607:user/release-keys" ||

       file_getprop("/system/build.prop", "ro.build.fingerprint") == "google/passion/passion/mahimahi:2.1-update1/ERE27/24178:user/release-keys");

檢測系統運行過程當中的屬性值

assert(getprop("ro.product.device") == "passion" ||

       getprop("ro.build.product") == "passion");

assert(getprop("ro.bootloader") == "0.33.2012" ||

       getprop("ro.bootloader") == "0.33.0012");

ui_print("Verifying current system...");

show_progress(0.100000, 0);

set_progress(0.001918);

檢測 patch 須要的空間

assert(apply_patch_space(6741176));

ui_print("Unpacking patches...");

釋放 patch 目錄下的內容到 /tmp/patchtmp

package_extract_dir("patch", "/tmp/patchtmp");

刪除不須要的文件...

ui_print("Removing unneeded files...");

刪除不須要的文件...

delete("/system/app/GoogleGoggles.apk", "/system/app/GoogleGoggles.odex",

       "/system/framework/svc.jar",

       "/system/recovery.img");

show_progress(0.800000, 0);

開始打補丁...

ui_print("Patching system files...");

升級設置程序的apk文件

apply_patch("/system/app/Settings.apk", "-",

            682e475c6411bb454d5999f6abff50ca8eb373f4, 1485651,

            "196c0891869ec4b93a738519daf30a56a96c570d:/tmp/patchtmp/system/app/Settings.apk.p");

set_progress(1.000000);

package_extract_dir("recovery", "/system");

show_progress(0.100000, 10);

ui_print("Unpacking new files...");

釋放 system 目錄下的內容到系統的 /system 目錄

package_extract_dir("system", "/system");

ui_print("Symlinks and permissions...");

set_perm_recursive(0, 0, 0755, 0644, "/system");

set_perm_recursive(0, 2000, 0755, 0755, "/system/bin");

set_perm(0, 3003, 02755, "/system/bin/netcfg");

set_perm(0, 3004, 02755, "/system/bin/ping");

set_perm(1001, 1005, 0444, "/system/etc/AudioPara4.csv");

set_perm_recursive(1002, 1002, 0755, 0440, "/system/etc/bluez");

set_perm(0, 0, 0755, "/system/etc/bluez");

set_perm(1002, 1002, 0440, "/system/etc/dbus.conf");

set_perm(1014, 2000, 0550, "/system/etc/dhcpcd/dhcpcd-run-hooks");

set_perm(0, 2000, 0550, "/system/etc/init.goldfish.sh");

set_perm(0, 0, 0544, "/system/etc/install-recovery.sh");

set_perm_recursive(0, 0, 0755, 0555, "/system/etc/ppp");

ui_print("Writing radio image...");

write_firmware_image("PACKAGE:radio.img", "radio");

unmount 系統目錄

unmount("/system");show_progress(0.100000, 10);

 

 

bootable/recovery/updater/updater.c

#define SCRIPT_NAME "META-INF/com/google/android/updater-script"

 

bootable/recovery/install.c:37:

#define ASSUMED_UPDATE_BINARY_NAME  "META-INF/com/google/android/update-binary"

mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);

 

int status = install_package(SDCARD_PACKAGE_FILE);

bootable/recovery/recovery.c:487:       

status = install_package(update_package);

經過 adb 登陸 G1 的分區信息:

/ # cat /proc/mtd

dev:    size   erasesize  name

mtd0: 00040000 00020000 "misc"

mtd1: 00500000 00020000 "recovery"

mtd2: 00280000 00020000 "boot"

mtd3: 05a00000 00020000 "system"

mtd4: 01e00000 00020000 "cache"

mtd5: 059c0000 00020000 "userdata"

高通 7630 分區信息:

$ cat /proc/mtd

dev:    size   erasesize  name

mtd0: 00500000 00040000 "boot"

mtd1: 06900000 00040000 "system"

mtd2: 00500000 00040000 "cache"

mtd3: 13480000 00040000 "userdata"

mtd4: 00300000 00040000 "persist"

mtd5: 00500000 00040000 "recovery"

這些信息是在文件 ./bootable/bootloader/lk/target/msm7630_surf/init.c 中指定的:

static struct ptentry board_part_list[] = {

    {

       .start = 0,

       .length = 20  /* 5MB */,

       .name = "boot",

    },

    {

       .start = 20,

       .length = 380 /* 95MB */,

       .name = "system",

    },

    {

       .start = 400,

       .length = 20 /* 5MB */,

       .name = "cache",

    },

    {

       .start = 420,

       .length = VARIABLE_LENGTH,

       .name = "userdata",

    },

    {

       .start = DIFF_START_ADDR,

       .length = 4 /* 1MB */,

       .name = "persist",

    },

    {

       .start = DIFF_START_ADDR,

       .length = 20 /* 5MB */,

       .name = "recovery",

    },

};

系統支持哪些flash的定義在文件 bootable/bootloader/lk/platform/msm_shared/nand.c 中:

static struct flash_identification supported_flash[] =

{

    /* Flash ID   ID Mask Density(MB)  Wid Pgsz   Blksz  oobsz onenand Manuf */

    {0x00000000, 0xFFFFFFFF,    0, 0, 0,     0,  0, 0}, /*ONFI*/

    {0x1500aaec, 0xFF00FFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Sams*/

    {0x5500baec, 0xFF00FFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Sams*/

    {0x1500aa98, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Tosh*/

    {0x5500ba98, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Tosh*/

    {0xd580b12c, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Micr*/

    {0x5590bc2c, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Micr*/

    {0x1580aa2c, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 0}, /*Micr*/

    {0x5580baad, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/

    {0x5510baad, 0xFFFFFFFF, (256<<20), 1, 2048, (2048<<6), 64, 0}, /*Hynx*/

    {0x004000ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/

    {0x005c00ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/

    {0x005800ec, 0xFFFFFFFF, (256<<20), 0, 2048, (2048<<6), 64, 1}, /*Sams*/

    {0x6600bcec, 0xFF00FFFF, (512<<20), 1, 4096, (2048<<6), 128, 0}, /*Sams*/

    /* Note: Width flag is 0 for 8 bit Flash and 1 for 16 bit flash    */

    /* Note: Onenand flag is 0 for NAND Flash and 1 for OneNAND flash   */

    /* Note: The First row will be filled at runtime during ONFI probe  */

};

 

pbl -> dbl -> osbl -> appsbl ->進入 recovery 模式

系統運行到 appsbl 階段纔開始是否進入 recovery 模式的處理。

 

 

int device_toggle_display(volatile char* key_pressed, int key_code) {

    return key_code == KEY_HOME;

}

 

 

 

check if nand misc partition has boot message. If yes, fill argc/argv.

If no, get arguments from /cache/recovery/command, and fill argc/argv.

 

讀取 /cache/recovery/command 文件的內容

FILE *fp = fopen_root_path(COMMAND_FILE, "r");

 

G1 的分區信息:

# cat /proc/mtd

dev:    size   erasesize  name

mtd0: 00040000 00020000 "misc"

mtd1: 00500000 00020000 "recovery"

mtd2: 00280000 00020000 "boot"

mtd3: 05a00000 00020000 "system"

mtd4: 01e00000 00020000 "cache"

mtd5: 059c0000 00020000 "userdata"

 

recovery_init() 調用的是文件 bootable/bootloader/lk/app/aboot/recovery.c中的函數:

/* Read and write the bootloader command from the "misc" partition.

 * These return zero on success.

 */

從 misc 分區讀取

misc         0.25MB:是存放開機畫面的分區,開機時那個白色的大G1字樣(默認爲白色"T-mobile G1")

recovery    5MB:是G1的恢復模式鏡像區(即開機按Home+End進入的界面)

Boot         2.5MB:Linux操做系統內核和ramdisk鏡像一塊兒打包後存放的分區

system      90MB:是system.img存放的分區,啓動後此鏡像掛載在根目錄下的system文件夾中。

cache        30MB:是緩存臨時文件夾,掛載爲/cache目錄,聽說是除了T-mobile的OTA更新外,別無用處。

userdata     89.75MB:用戶安裝的軟件以及各類數據,掛載爲/data目錄

msm_nand     256MB:表明整個Nand Flash,不是一個分區。可是全部的分區加起來才217.5MB,小於256MB,說明還有剩餘的flash空間。(此分區在大部分機上不存在,不影響使用)

 

 

恢復模式的 init.rc 文件很簡單,只啓動了 recovery 和 adbd 服務

on init

    export PATH /sbin

    export ANDROID_ROOT /system

    export ANDROID_DATA /data

    export EXTERNAL_STORAGE /sdcard

    symlink /system/etc /etc

    mkdir /sdcard

    mkdir /system

    mkdir /data

    mkdir /cache

    mount /tmp /tmp tmpfs

on boot

    ifup lo

    hostname localhost

    domainname localdomain

    class_start default

service recovery /sbin/recovery

service adbd /sbin/adbd recovery

on property:persist.service.adb.enable=1

    start adbd

on property:persist.service.adb.enable=0

    stop adbd

 

4.1.3.4.2 Recovery 模式中 install_package 函數解析

設置模塊中系統升級和sd卡方式軟件升級會調用 install_package 函數

int status = install_package(SDCARD_PACKAGE_FILE);

status = install_package(update_package);

bootable/recovery/install.c:322:install_package(const char *root_path)

int install_package(const char *root_path)

{

    ui_set_background(BACKGROUND_ICON_INSTALLING);

    ui_print("Finding update package...\n");

    ui_show_indeterminate_progress();

    LOGI("Update location: %s\n", root_path);

 

    if (ensure_root_path_mounted(root_path) != 0) {

        LOGE("Can't mount %s\n", root_path);

        return INSTALL_CORRUPT;

    }

 

    char path[PATH_MAX] = "";

    if (translate_root_path(root_path, path, sizeof(path)) == NULL) {

        LOGE("Bad path %s\n", root_path);

        return INSTALL_CORRUPT;

    }

 

    ui_print("Opening update package...\n");

    LOGI("Update file path: %s\n", path);

 

int numKeys;

# #define PUBLIC_KEYS_FILE "/res/keys"

    RSAPublicKey* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys);

    if (loadedKeys == NULL) {

        LOGE("Failed to load keys\n");

        return INSTALL_CORRUPT;

    }

    LOGI("%d key(s) loaded from %s\n", numKeys, PUBLIC_KEYS_FILE);

 

    // Give verification half the progress bar...

    ui_print("Verifying update package...\n");

    ui_show_progress(

            VERIFICATION_PROGRESS_FRACTION,

            VERIFICATION_PROGRESS_TIME);

 

    int err;

    err = verify_file(path, loadedKeys, numKeys);

    free(loadedKeys);

    LOGI("verify_file returned %d\n", err);

    if (err != VERIFY_SUCCESS) {

        LOGE("signature verification failed\n");

        return INSTALL_CORRUPT;

    }

 

    /* Try to open the package.

     */

    ZipArchive zip;

    err = mzOpenZipArchive(path, &zip);

    if (err != 0) {

        LOGE("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad");

        return INSTALL_CORRUPT;

    }

 

    /* Verify and install the contents of the package.

     */

    int status = handle_update_package(path, &zip);

    mzCloseZipArchive(&zip);

    return status;

}

 

4.1.3.5 Recovery 流程分析

4.1.3.5.1 恢復出廠設置

addPreferencesFromResource(R.xml.privacy_settings);

菜單描述在文件 packages/apps/Settings/res/xml/privacy_settings.xml

<PreferenceScreen

                android:title="@string/master_clear_title"

                android:summary="@string/master_clear_summary">

            <intent android:action="android.intent.action.MAIN"

                    android:targetPackage="com.android.settings"

                    android:targetClass="com.android.settings.MasterClear" />

</PreferenceScreen>

恢復出廠設置執行的是 activiy MasterClear

packages/apps/Settings/src/com/android/settings/MasterClear.java

-> service.masterClear() 調用文件:

frameworks/base/services/java/com/android/server/FallbackCheckinService.java 中的函數:

public void masterClear()

RecoverySystem.rebootAndWipe()

bootCommand("--wipe_data");

    把內容 "--wipe_data" 寫入到文件 /cache/recovery/command 中

Power.reboot("recovery");

補充:

private static File RECOVERY_DIR = new File("/cache/recovery");

private static File COMMAND_FILE = new File(RECOVERY_DIR, "command");

private static File LOG_FILE = new File(RECOVERY_DIR, "log");

命令文件: /cache/recovery/command

log文件/cache/recovery/log

 

Install: out/target/product/msm7630_surf/root/sbin/adbd

target Non-prelinked: init (out/target/product/msm7630_surf/symbols/init)

target Non-prelinked: adbd (out/target/product/msm7630_surf/symbols/sbin/adbd)

 

4.1.3.5.2 系統更新流程

在設置模塊 -> 關於手機 裏面預設了 「系統更新」 的菜單項配置, 若是安裝的軟件包裏面有過濾器爲:

<intent-filter>

<action android:name="android.settings.SYSTEM_UPDATE_SETTINGS" />

    <category android:name="android.intent.category.DEFAULT" />

</intent-filter>

的軟件包,那麼纔會顯示 」系統更新」 的菜單項,不然沒有該項菜單。此類菜單的處理方式經過文件:

packages/apps/Settings/src/com/android/settings/Utils.java 中的函數

updatePreferenceToSpecificActivityOrRemove 來實現。

Android 源代碼中爲系統升級包預留了位置  packages/apps/Updater/ 可是沒有具體的源代碼,這個源代碼能夠由廠商本身開發,這樣作是爲了方便廠商靈活的定製系統升級方式。

在 HTC 手機中該軟件包一般爲: SystemUpdater.apk 咱們能夠從他們的手機中提取。

 

流程應該爲:

應用模塊中調用:service.systemUpdate() 實際調用的是文件:

frameworks/base/services/java/com/android/server/FallbackCheckinService.java

中的函數:

public void systemUpdate()

{

    RecoverySystem.rebootAndUpdate();

}

 

frameworks/base/services/java/com/android/server/SystemUpdateReceiver.java

public class SystemUpdateReceiver extends BroadcastReceiver {

    private static final String TAG = "MasterClear";

    @Override

    public void onReceive(Context context, Intent intent) {

        ICheckinService service =

            ICheckinService.Stub.asInterface(

                ServiceManager.getService("checkin"));

              ...

                service.systemUpdate();

              ...

}

frameworks/base/core/java/android/os/ICheckinService.aidl

中加函數函數聲明:

void systemUpdate();

rebootAndUpdate 函數應該爲:

frameworks/base/core/java/com/android/internal/os/RecoverySystem.java

    public static void rebootAndUpdate(File update) throws IOException {

        String path = update.getCanonicalPath();

        if (path.startsWith("/cache/")) {

            path = "CACHE:" + path.substring(7);

        } else if (path.startsWith("/data/")) {

            path = "DATA:" + path.substring(6);

        } else {

            throw new IllegalArgumentException(

                    "Must start with /cache or /data: " + path);

        }

        bootCommand("--update_package=" + path);

}

getCanonicalPath() 獲取文件的絕對路徑

getAbsolutePath()和getCanonicalPath()的不一樣

public static void test2() throws Exception{

        File file = new File("../update.zip");

        System.out.println(file.getAbsolutePath());

        System.out.println(file.getCanonicalPath());

    }

獲得的結果

/data/bin/../update.zip

/data/update.zip

 

bootCommand("--update_package=" + path) 會寫命令:

--update_package= CACHE:/cache/xxxx  或者 --update_package= DATA:/data/xxxx 到命令文件:

/cache/recovery/command

 

重啓之後,會檢查命令文件 /cache/recovery/command

    // --- if that doesn't work, try the command file

    if (*argc <= 1) {

        FILE *fp = fopen_root_path(COMMAND_FILE, "r");

        if (fp != NULL) {

            char *argv0 = (*argv)[0];

            *argv = (char **) malloc(sizeof(char *) * MAX_ARGS);

            (*argv)[0] = argv0;  // use the same program name

 

            char buf[MAX_ARG_LENGTH];

            for (*argc = 1; *argc < MAX_ARGS; ++*argc) {

                if (!fgets(buf, sizeof(buf), fp)) break;

                (*argv)[*argc] = strdup(strtok(buf, "\r\n"));  // Strip newline.

            }

 

            check_and_fclose(fp, COMMAND_FILE);

            LOGI("Got arguments from %s\n", COMMAND_FILE);

        }

    }

static const struct option OPTIONS[] = {

  { "send_intent", required_argument, NULL, 's' },

  { "update_package", required_argument, NULL, 'u' },

  { "wipe_data", no_argument, NULL, 'w' },

  { "wipe_cache", no_argument, NULL, 'c' },

  { NULL, 0, NULL, 0 },

};

 

while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {

        switch (arg) {

        case 'p': previous_runs = atoi(optarg); break;

        case 's': send_intent = optarg; break;

相關文章
相關標籤/搜索