GrabDuck

Сборка Qualcomm модема из исходников (msm8916)

:

Ради фана и прокачки скилов решил собрать Qualcomm модем из исходников. В качестве целевой платформы выбрал msm8916, т.к. именно под эту платформу можно скачать исходники из интернета.

Для начала нужно скачать эти самые исходники. Для этого нужно воспользоваться торрент клиентом. Сам торрент можно найти, если загуглить строку EF3BF4FD7388657FF35C3DBF2B6367F924F8CDBC (magnet link). Скачивать можно не всё содержимое торрента, а только файл
" msm8916_2014-12-03_amss_qrd/modem_proc.zip" (500 MB).

Для сборки исходников модема msm8916 нам понадобится пакет  HEXAGON Tools v6. Этот пакет входит в состав Hexagon SDK v2.0 - Linux. Но почему то консольный вариант установки этого SDK зависает на 30%. Поэтому предлагаю скачать отдельно HEXAGON Tools 6.4.06 вот отсюда: download (170 MB).

Пока скачиваются тулзы и торрент следует распаковать NON-HLOS образ, который следует взять из прошивки целевого устройства. В моём случае этим устройством будет являться ASUS ZE550KL, т.к. разработчики из ASUS все свои модемы подписыват тестовым сертификатом Qualcomm (данный сертификат имеется в исходниках).
Распаковка образа NON-HLOS.bin осущестляется таким образом:

MODEM_DIR=$HOME/dev/asus_ze550kl
MODEM_STK=$MODEM_DIR/NON-HLOS.bin
MODEM_VDISK=/media/vdisk
sudo mkdir -p $MODEM_VDISK
sudo mount -t vfat $MODEM_STK -o ro $MODEM_VDISK
cp -f -r $MODEM_VDISK/* $MODEM_DIR
sudo umount $MODEM_STK

После этого в директории " dev/asus_ze550kl/image" должен появиться следующий набор файлов:
mba.mbn
modem.b00
modem.b01
modem.b02
...
modem.b25
modem.b26
modem.mdt

После скачивания торрента и утилит, при помощи которых будет осуществляться сборка модема msm8916, можно приступить к настройке операционной системы (рекомендую использовать Ubuntu 14.04 64-bit).

Для начала нужно установить некоторые зависимости:

sudo apt-get install p7zip-full
sudo apt-get install lib32z1 lib32ncurses5
sudo apt-get install scons
sudo apt-get install libxml-parser-perl

Установим HEXAGON Tools в систему из директории ~/Downloads:
cd $HOME
mkdir -p Qualcomm/HEXAGON_Tools
cd $HOME/Downloads
7za x -y -o$HOME/Qualcomm/HEXAGON_Tools hexagon_tools_6.4.06.7z

Распакуем исходники модема msm8916 в директорию ~/dev/qcom:
cd $HOME
mkdir -p dev/qcom/msm8916/modem_proc
cd $HOME/Downloads/msm8916_2014-12-03_amss_qrd
7za x -y -o$HOME/dev/qcom/msm8916/modem_proc modem_proc.zip

Т.к. zip-архив не хранит информацию о UNIX-атрибутах, следует устранить это недоразумение:
cd $HOME/dev/qcom/msm8916/modem_proc
find . -name '*.sh' -exec chmod -f 775 {} \;
find . -name '*.mk' -exec chmod -f 775 {} \;
find . -name '*.py' -exec chmod -f 775 {} \;
find . -name '*.pl' -exec chmod -f 775 {} \;
find . -name '*.lcs' -exec chmod -f 775 {} \;
find . -name '*.api' -exec chmod -f 775 {} \;
find . -name '*.xml' -exec chmod -f 775 {} \;
find . -name '*.scons' -exec chmod -f 775 {} \;
find . -name 'scons' -exec chmod -f 775 {} \;
find . -name 'SConscript' -exec chmod -f 775 {} \;
find . -name 'SConstruct' -exec chmod -f 775 {} \;
find . -name 'Makefile' -exec chmod -f 775 {} \;
find . -name 'makefile' -exec chmod -f 775 {} \;
find . -name 'qaic' -exec chmod -f 775 {} \;
find . -name 'doxygen' -exec chmod -f 775 {} \;
find . -name 'qdsp6-image-build' -exec chmod -f 775 {} \;
find . -name 'SleepSynth' -exec chmod -f 775 {} \;
find . -name 'crypto_cbc' -exec chmod -f 775 {} \;
find . -name 'crypto_ccm' -exec chmod -f 775 {} \;

Перейдём в директорию " modem_proc/build/ms" , т.к. именно тут находится shell-скрипт, запускающий процесс сборки. Так же в этой директории следует ожидать появления результатов сборки в поддиректории " bin". Перед запуском сборки нужно превести предварительную настройку. Откройте в тектовом редакторе файл build.sh и выполните следующие изменения:
1) удалите первую строчку, содержащую строку " #!/bin/sh"
2) замените строку " source setenv.sh" на " . setenv.sh"

В этой же директории нужно создать файл setenv.sh со следующим содержанием:

export ARMTOOLS=ARMCT5.05
export ARMROOT=$HOME/ARMCompiler5.05u2
export ARM_COMPILER_PATH=$ARMROOT/bin64
export ARMHOME=$ARMROOT
export ARMLIB=$ARMROOT/lib
export ARMINCLUDE=$ARMROOT/include
export ARMBIN=$ARMROOT/bin64
export ARMINC=$ARMINCLUDE
export ARMLMD_LICENSE_FILE=$ARMROOT/Community.lic

export HEXAGON_ROOT=$HOME/Qualcomm/HEXAGON_Tools
export HEXAGON_RTOS_RELEASE=6.4.06
export HEXAGON_Q6VERSION=v5
export HEXAGON_IMAGE_ENTRY=0xC0000000

export PYTHON_PATH=/usr/bin/python
export PYTHONPATH=/usr/bin/python
export MAKE_PATH=/usr/bin/make

export PATH=$MAKE_PATH:$ARM_COMPILER_PATH:$HEXAGON_ROOT/$HEXAGON_RTOS_RELEASE/qc/bin:$HEXAGON_ROOT/$HEXAGON_RTOS_RELEASE/gnu/bin:$PATH:PYTHONPATH

Хочется обратить внимание на значение параметра HEXAGON_IMAGE_ENTRY. Данное значение следует искать в стоковом модеме:
cd $HOME/dev/asus_ze550kl/image
readelf -h modem.b00

На входе получаем такую информацию о стоковом образе модема:
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           QUALCOMM DSP6 Processor
  Version:                           0x1
  Entry point address:               0xc0000000
  Start of program headers:          52 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x4
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         28
  Size of section headers:           40 (bytes)
  Number of section headers:         0
  Section header string table index: 0

Из всего этого нас интересует только значение параметра " Entry point address", равное 0xC0000000.

Теперь откройте в текстовом редакторе файл build_cfg.xml и сделайте следующие изменения:
1) значение параметра hexagon_image_entry измените на " 0xC0000000"
2) значение параметра hexagon_rtos_release измените на " 6.4.06"
3) значение параметра cflags измените на
" -Wno-error -Wno-tautological-constant-out-of-range-compare -Wno-medium -Wno-low -hexagon-predef-argset=modem-sw -mllvm -shrink-wrap-ext-wrapper-section=.wrap.func"

Далее нужно исправить досадную ошибку в файле " modem_proc/build/bsp/mapss_b/build/mapss_b.scons". Для этого откройте его в текстовом редакторе, найдите вот такой участок кода:

legacy_mode = True

if hex_version[0] >= '7':
  legacy_mode = False

elif hex_version[0] == '6':
  if hex_version[1] == '2':
    if len(hex_version) >= 3 and hex_version[2] >= '06':
      legacy_mode = False
  elif hex_version[1] == '4':
    legacy_mode = False

и добавьте 2-ве выделенных строчки кода (в оригинале они отсутствуют).

Теперь нужно добавить версию HEXAGON Tools 6.4.06 в белый список:

cd $HOME/dev/qcom/msm8916/modem_proc/core/kernel/qurt
HEXAGON_RTOS_RELEASE=6.4.06
WL_PREFIX="toolsver_whitelist \\= \\["
find . -name 'target_tools.py' -exec sed -i "s/$WL_PREFIX/$WL_PREFIX\"$HEXAGON_RTOS_RELEASE\" ,/" {} \;

Перед началом сборки следует определиться с вариантом собираемого модема. Для этого следует в распакованном образе NON-HLOS.bin найти строку " IMAGE_VARIANT_STRING=":
cd $HOME/dev/asus_ze550kl/image
grep -aohP "IMAGE_VARIANT_STRING=.{0,8}" modem.b*
Результат поиска таков: "IMAGE_VARIANT_STRING=EAAAANUZ"

Далее стоит в редактируемом ранее файле build_cfg.xml найти соответствие для строки " EAAAANUZ" найти вариант сборки:

 
    <build_variant>
      <variant_name> gen </variant_name>
      <purpose> 
        <purpose_name>prod</purpose_name>
        <build_id>  EAAAANVZ  </build_id>
      </purpose>
    </build_variant>
    <build_variant>
      <variant_name> genns </variant_name>
      <purpose> 
        <purpose_name>prod</purpose_name>
        <build_id>  EAAAANUZ  </build_id>
      </purpose>
    </build_variant>

Значит разработчики из ASUS используют вариант сборки " genns".

Запускаем сборку модема:

cd $HOME/dev/qcom/msm8916/modem_proc/build/ms/
./build.sh 8916.genns BUILD_ID=EAAAANUZ -k

Через некоторое время процесс сборки остановится и выдаст следующие ошибки:
** Build errors...
/home/android/dev/qcom/msm8916/modem_proc/geran/gmac/build/mapss_b/qdsp6/EAAAANUZ/gmacidleutil.o failed: Error 1
/home/android/dev/qcom/msm8916/modem_proc/geran/gmac/build/mapss_b/qdsp6/EAAAANUZ/gmacutil.o failed: Error 1

Сначала исправим ошибку в gmacidleutil.c:
 
     else
     {
       if( /*(((starting_time_fn - reception_fn_mod_42432) % 42432) >= 0)
           &&*/ (((starting_time_fn - reception_fn_mod_42432) % 42432) <= 31623))
       {

Т.е. нужно всего навсего закоментировать первую часть условия.
В файле gmacutil.c нужно исправить полностью аналогичную ошибку.

Теперь можно снова запустить сборку исходников:

cd $HOME/dev/qcom/msm8916/modem_proc/build/ms/
./build.sh 8916.genns BUILD_ID=EAAAANUZ -k

Хочу сразу отметить, что если вам понадобиться начать сборку с самого начала, то перед этим нужно выполнить " clean". Для этого нужно в консоли ввести следующее:
cd $HOME/dev/qcom/msm8916/modem_proc/build/ms/
./build.sh 8916.genns BUILD_ID=EAAAANUZ --clean

Через некоторое время процесс сборки должен завершиться и при успехе вы в консоли должны увидить следующие строки:
#-------------------------------------------------------------------------------
Build 8916.genns returned code 0.
#-------------------------------------------------------------------------------
Overall Start Time: Sun Aug 14 16:26:43 2016,  Overall End Time: Sun Aug 14 16:31:21 2016
Overall Delta Time: 4 minutes, 37 seconds
#-------------------------------------------------------------------------------

Результаты сборки следует искать в директории " dev/qcom/msm8916/modem_proc/build/ms/":
./build.log
./bin/EAAAANUZ/mba.mbn
./bin/EAAAANUZ/qdsp6sw.mbn
./bin/EAAAANUZ/unsigned/mba.mbn
./bin/EAAAANUZ/unsigned/qdsp6sw.mbn

Т.к. в стоковом образе NON-HLOS.bin используются подписанные модули, то нужно использовать для дальнейших операций файлы " EAAAANUZ/mba.mbn" и " EAAAANUZ/qdsp6sw.mbn". Оба файла подписаны тестовым сертификатом Qualcomm.
Теперь нужно файл qdsp6sw.mbn разбить на множество более мелких файлов, которые представляют из себя ELF-секции исходного MBN-файла. Для этого нужно выполнить следующее:
cd $HOME/dev/qcom/msm8916/modem_proc/build/ms/bin
wget http://github.com/remittor/qcom-mbn-tools/raw/master/pil-splitter.py

BUILD_ID=EAAAANUZ
MBN_FILE=./$BUILD_ID/qdsp6sw.mbn
MBN_PREFIX=modem
cd $HOME/dev/qcom/msm8916/modem_proc/build/ms/bin
python pil-splitter.py $MBN_FILE $MBN_PREFIX

После выполнения скрипта pil-splitter.py в директории " bin" появится следующий набор файлов:
modem.b00
modem.b01
modem.b02
...
modem.b24
modem.b25
modem.mdt

Так же в эту папку следует добавить файл mba.mbn , что можно сделать таким способом:
BUILD_ID=EAAAANUZ
MBN_FILE=./$BUILD_ID/mba.mbn
cd $HOME/dev/qcom/msm8916/modem_proc/build/ms/bin
cp -f $MBN_FILE ./

Далее нужно полученные файлы добавить в стоковый образ NON-HLOS.bin. Эту операцию можно осуществить следующим способом:
MODEM_DIR=$HOME/dev/asus_ze550kl
MODEM_STK=$MODEM_DIR/NON-HLOS.bin
MODEM_NEW=$MODEM_DIR/NON-HLOS-NEW.bin
MODEM_VDISK=/media/vdisk
cp -f $MODEM_STK $MODEM_NEW
sudo mkdir -p $MODEM_VDISK
sudo mount -t vfat $MODEM_NEW -o rw,umask=0000 $MODEM_VDISK
rm -f $MODEM_VDISK/image/modem.mdt
rm -f $MODEM_VDISK/image/modem.b*
rm -f $MODEM_VDISK/image/mba.*
cd $HOME/dev/qcom/msm8916/modem_proc/build/ms/bin
cp -f ./modem.mdt $MODEM_VDISK/image/
cp -f ./modem.b* $MODEM_VDISK/image/
cp -f ./mba.* $MODEM_VDISK/image/
sudo umount $MODEM_NEW

Теперь у нас имеется файл NON-HLOS-NEW.bin , который содержит новые бинарные модули, относящиеся непосредственно к модему. Осталось только проверить работоспособность этого образа NON-HLOS-NEW.bin. Но сделать этого я не могу, т.к. у меня нету девайса ASUS ZE550KL.

Поэтому я оставлю тут патч для TWRP, который устанавливает в девайс ASUS ZE550KL этот новый модем:  modem_test_005.zip (только для модификации Z00L на чипе msm8916)