Как отлаживать Android ядро без UART, JTAG и прочих

    Довольно часто разработчики ядер под Android устройства сталкиваются с тем, что собранное из исходников ядро просто напросто не работает. И при этом часто разработчик, собравший ядро, не имеет никаких специальных средств для отладки. В данной ситуации без kmsg логов довольно трудно что либо сделать. Конечно же в Linux ядре уже имеется несколько способов копирования содержимого kmsg буфера в специальную область памяти, но если вам интересно узнать ещё об одном способе, то прошу под кат.

    Недавно я уже описывал одну из возможностей модуля LLCON, которая заключалась в отображении kmsg логов на дисплее Android устройства. Теперь настало время описать похожий механизм копирования kmsg логов, т.к. отображение логов на экране не очень удобно для поиска всевозможных ошибок.

    Для начала стоит отметить тот факт, что в большинстве случаев оперативная память Android устройства не очищается при рестарте SoC. Эту особенность использует механизм, который обеспечивает появление файла /proc/last_kmsg. Но порой для принудительного рестарта SoC приходится долго удерживать кнопку Power, что влечёт за собой либо полное, либо частичное изменение содержимого оперативной памяти. В данном случае я рекомендую подключать устройство к ПК через USB-кабель, что бы содержимое оперативной памяти не изменялось (по крайней мере на моём устройстве это работает).

    Поэтому при старте первым же делом тестовое ядро должно зарезервировать некоторую область оперативной памяти для дублирования в оную содержимого kmsg буфера. Я обычно под это дело выделяю 1 MiB памяти, а в качестве физического адреса использую 0x7f200000, т.к. на моём устройстве установлено 2 GiB SDRAM.

    Т.е. на своём Android устройстве для включения данного функционала я в командную строку ядра добавляю дополнительный параметр:

    llcondmp=0x7f200000,0x100000

    Пример добавления параметра llcondmp в BoardConfig
    BOARD_KERNEL_CMDLINE := androidboot.hardware=qcom
    BOARD_KERNEL_CMDLINE += androidboot.selinux=permissive
    BOARD_KERNEL_CMDLINE += msm_rtb.filter=0x37
    BOARD_KERNEL_CMDLINE += user_debug=31 debug ignore_loglevel
    BOARD_KERNEL_CMDLINE += llcondmp=0x7f200000,0x100000

    Тестовое ядро, в котором имеется модуль LLCON, при запуске должно обработать данный параметр и зарезервировать указанную область оперативной памяти. При этом будет включён механизм, который будет дублировать kmsg логи и в эту специально подготовленную область памяти. Причём данное дублирование будет осуществляться внутри вызова функции printk (т.е. моментально и прозрачно). Данное обстоятельство позволяет получать kmsg логи даже при экстренном рестарте SoC тестируемого устройства.

    После рестарта SoC нужно каким то образом прочитать содержимое этой области памяти. Для этого бутлоадер должен загрузить что то стабильно рабочее, коим вполне может являться TWRP, основанное на стоковом ядре. Но этот TWRP должен уметь резервировать в оперативной памяти туже область, что бы его содержимое оставалось нетронутым. Т.е. нужно предварительно сделать и прошить специальную версию TWRP.

    Для того, что бы используемое в TWRP ядро зарезервировало в оперативной памяти участок 0x7f200000...0x7f2FFFFF, нужно отредактировать DeviceTree этого ядра. Сам процесс редактирования DeviceTree требует написания отдельной статьи, поэтому я всего лишь приведу само изменение в dts-файле:

    /dts-v1/;
    /memreserve/ 0x7f200000 0x100000;  /* добавленная строка */
    /include/ "msm8226-v2.dtsi"
    /include/ "msm8226-qrd.dtsi"

    Но на этом переделка TWRP не завершена. Нужно в ramdisk добавить утилиту viewmem, которая позволяет сбрасывать содержимое физической памяти на диск. Исходники данной утилиты можно скачать тут: viewmem.

    Где можно взять готовый бинарь viewmem
    Если сборкой TWRP из исходников замарачиваться совсем не хочется, то советую исходники viewmem добавить в тот же проект, который используется для сборки тестового ядра. И уже готовый бинарный файл viewmem просто встроить в нужный образ TWRP.

    После подготовки специальной версии TWRP оный нужно залить в устройство. Причём для тестирования кастомных ядер этот TWRP я советую заливать в раздел «boot», т.к. именно на его содержимое бутлоадер передаёт управление по-умолчанию. Описывать способы заливки образов разделов здесь не стану, что бы совсем не выбивается из тематики данной публикации.

    Для начала стоит опробовать работу установленного в устройство специальной версии TWRP. Можно даже проверить работу утилиты viewmem (см. ниже пример использования). Так же замечу, что для рестарта этого TWRP следует в разделе меню «Restart» выбирать пункт «System», т.к. TWRP у нас находится в разделе «boot».

    Теперь у нас есть специальный TWRP и тестовое ядро с модулем LLCON, которое либо зависает, либо заставляет SoC ребутиться. И этого вполне достаточно для поиска причин такого поведения тестового ядра. Образ тестируемого ядра я рекомендую заливать в раздел «recovery». Поэтому для начала тестирования проблемного ядра следует в разделе меню «Restart» выбрать пункт «Recovery». Это будет означать то, что при перезагрузке устройства бутлоадер передаст управление на содержимое раздела «recovery». Далее следует дождаться возникновения ошибки в тестируемом ядре. Если ошибка сама вызывает рестарт SoC, то делать ничего не нужно, т.к. должен автоматически загрузиться ранее подготовленный TWRP. Если же ошибка вызывает зависание, то зажмите кнопку Power и дождитесь хардварного рестарта (главное не забудьте про USB-кабель).

    Загрузившись в TWRP нужно первым же делом при помощи ADB-соединения скопировать kmsg логи из памяти на диск:

    adb shell
    viewmem 0x7f200000 0x100000 > /sdcard/kmsg_llcon.txt
    exit

    Теперь нужно с SD-карты скопировать файл kmsg_llcon.txt и начать изучать его содержимое.

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

    • создание кастомного ядра версии 3.4 для устройства Innos D10F (2014 год);
    • создание кастомного ядра версии 3.4 для устройства Innos D9 (2015 год);
    • создание кастомного ядра версии 3.10 для устройства Innos D10F (текущий проект).

    Так что при разработке Android ядер можно вполне обойтись и без UART, JTAG, EmbeddedICE DCC и прочих средств, использующихся для отладки.

    Примечание: исходники модуля LLCON ищите в моей прошлой публикации "Заменяем бут-анимацию Android устройства на мелькающие логи Linux ядра".
    • +15
    • 8,2k
    • 9
    Поделиться публикацией

    Комментарии 9

      0
      Вопрос времени и денег?
      Присесть лишний раз не сложно и это бесплатно, но опять же тратишь время. Не задумывались над этим?
        0
        Вопрос времени и денег?
        Времени действительно мало, но думаю тут дело в другом. Просто когда встречается какая то проблема, то у меня появляется спортивный интерес в ее преодалении. В данном случае так и было.
        Присесть лишний раз не сложно и это бесплатно...
        Куда вы мне предлагаете присесть?
        0
        acDev, спасибо за статьи!
        Мне интересен embedded android, но не знаю, как сделать первый шаг.
        Думаю я не один такой)
        Напишите пожалуйста статью getting started для новичков в этом деле?

        Пробовал поиграться со своим смартфоном и выяснил что он проблемный:
        http://lenovo-forums.ru/topic/12336-lenovo-s60-%D1%80%D0%B0%D0%B7%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0-bootloader/?page=2

        Я так понимаю, что Innos D10F полностью открытый?
          0
          Напишите пожалуйста статью getting started для новичков в этом деле?
          Я уже давал развёрнутый ответ на данный вопрос: #comment_9827690
          Я так понимаю, что Innos D10F полностью открытый?
          Изначально был закрытый, т.к. производитель ни под один свой продукт не публиковал исходники.
          Но теперь под это устройство имеются исходники ядра, исходники бутлоадера и исходники проприетарных библиотек Qualcomm. И вот при наличии всех этих исходников можно считать этот девайс полностью открытым. Он даже более открытый чем Nexus 5 для разрабов.
          А всё потому, что очень редкая китайская контора парится с подписью загрузчиков при сборке прошивок. Даже сейчас можно купить брендованное Android устройство, в котором присутствуют системные образы подписанные тестовым сертификатом Qualcomm, закрытая часть которого известна.
          Поэтому нужно сказать ленивым китайцам спасибо. Особенно тем, кто не парится по поводу безопасности своего рабочего места (у таких вот и сливают обычно ключи IDA Pro и сорцы проприетариев Qualcomm).
            0
            исходники проприетарных библиотек Qualcomm
            А RIL тоже есть? У меня другой аппарат (Droid Incredible 4G LTE), и на последних CM не работает CDMA-радио, хочу попытаться разобраться.
            С исходниками пусть и от другого аппарата будет проще, думаю.
              +1
              А RIL тоже есть?
              Конечно же есть. Ищите тут: http://v2.pikacode.com/jsr-d10
              на последних CM не работает CDMA-радио, хочу попытаться разобраться
              С последними CM (CM12.1, CM13, CM14) и ядром версии 3.4 исходники из предоставленной ссылки не получится заюзать.
              Для msm8226 я пока использовал проприетарии версии 4.4.4. Для использования проприетариев 5.1.1 я сейчас пробую для msm8226 собрать ядро версии 3.10, без которого эти проприетарии требуют в множестве мест отката.
                0
                Спасибо!
                С последними CM (CM12.1, CM13, CM14) и ядром версии 3.4 исходники из предоставленной ссылки не получится заюзать.
                Ну для более легкого понимания куда копать — думаю хватит. Врядли они логику меняли сильно.
                Тем более что на CM11 всё работало, при обновлении до CM12.1 тоже работает, но если накатить 12.1 на чистую — то нет. Ну и на последних 12.1 тоже вырубается, независимо на чистую или обновлением.
                Всё это крутится на ядре 3.4.105.

                Родной был Android 4.0.4
              0
              Этот комментарий я пропустил)
              Объясните пожалуйста, почему я не найду где купить планшет Nexus 7 (2013)/9?
              Всюду «out of stock». Программисты разбирают?
            0
            компиляция ядра для Innos D10F сильно отличается от аглоритма, описанного в этом блоге:
            http://pete.akeo.ie/2013/10/compiling-and-running-your-own-android.html
            ?

            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

            Самое читаемое