Инженер написал драйвер для кнопки Power в FreeBSD, разобравшись в ACPI за две недели
Российский разработчик столкнулся с тем, что на ноутбуке HP Laptop 15s под управлением FreeBSD 15.0 не работала кнопка выключения питания. Разбирательство с таблицами ACPI и отладка ядра заняли две недели и завершились написанием собственного модуля gpiopwrb.
История началась с того, что автор материала уговорил коллегу установить FreeBSD 15.0 на рабочий ноутбук HP Laptop 15s в качестве второй системы. Установка на отдельный раздел диска прошла успешно: беспроводная карта Wi-Fi и встроенная графика AMD заработали сразу, поверх Xorg поставили окружение Xfce4 и повседневное программное обеспечение. Проблема обнаружилась в момент, когда коллега собрался уходить домой и нажал кнопку питания — система никак не отреагировала, хотя команда shutdown отрабатывала корректно и завершала работу с выключением питания. Автор вспомнил про переменную hw.acpi.power_button_state, отвечающую за поведение системы при нажатии кнопки Power, и установил её в значение S5, соответствующее выключению питания, но это ни к чему не привело.
Тогда разработчик включил режим многословности ядра и принялся многократно нажимать кнопку, наблюдая за сообщениями на консоли. Ни одного события от ACPI зафиксировано не было, что указывало либо на физическую неисправность кнопки, либо на поломку обработки ACPI в ядре FreeBSD. Проверка в Windows показала, что кнопка исправна и штатно выключает ноутбук, поэтому единственным разумным объяснением оставалась ошибка в реализации ACPI на стороне FreeBSD. Автор решил не оставлять коллегу с нерабочей системой и взялся за отладку ядра, растянувшуюся на две недели ночной работы тайком от семьи. Результатом стал собственный небольшой драйвер для кнопки Power и подробный разбор технологии Advanced Configuration and Power Interface, изложенный в формате большого технического руководства.
В тексте последовательно разобраны уровни подсистемы ACPI: поддержка произвольных источников событий GPE, обработка событий через GPIO, корневые пространства имён, служебные объекты и их методы, идентификаторы Hardware ID и UUID. Отдельно описаны ключевые таблицы прошивки — FADT, FACS и DSDT, а также язык ACPI Machine Language и его Си-подобное представление ASL, включая оператор Notify() для отправки нотификаций в OSPM и процедуры компиляции и декомпиляции. Практическая часть начинается со снятия дампа таблиц ACPI с ноутбука HP Laptop 15s, их декомпиляции в BSD-версии, компиляции ASL-кода и подстановки исправленной таблицы DSDT, после чего ядро загружается в режиме многословности и вызываются методы ACPI из командной строки. Автор также касается методов \_OSI и \_OS, через которые прошивка запрашивает тип операционной системы и её возможности, что важно для понимания логики ветвления в DSDT.
Поиск причины неисправности кнопки Power занял центральную часть материала: разработчик включил режим отладки для ACPICA, скачал исходные коды FreeBSD 15.1-RELEASE, собрал отладочное ядро и получил диагностическую информацию от подсистемы. Анализ кода ACPI показал, что событие PWRB попросту не формируется, и дальше пришлось разбираться с обработкой событий от встроенного контроллера через методы EC0._Qxx и от GPIO через метод GPIO._EVT. Отдельные разделы посвящены драйверу GPIO-контроллера для процессоров AMD amdgpio, взаимодействию с GPIO в FreeBSD через шину GPIO, модулю gpioaei, вызывающему метод _EVT при смене состояния линий, а также подсистеме обработки аппаратных прерываний, где аппаратные прерывания рассматриваются как виртуальный ресурс global IRQ.
Кульминацией стала разработка модуля gpiopwrb, который протезирует прерывания от кнопки Power. Автор подробно описывает структуру драйвера-модуля в FreeBSD: методы устройства, методы экспортируемого интерфейса, регистрацию драйвера в Nexus и сборочный скрипт Makefile. Далее разобрана внутренняя структура модуля gpiopwrb, контекст struct gpiopwrb_softc, инициализация и деинициализация, реализация методов device_identify, device_probe, device_attach и device_detach, а также поток gpiopwrb_daemon. Отдельное внимание уделено сборке и тестированию модуля, подготовке man-странички с использованием подсистемы встроенной документации mdoc и установке драйвера в систему. Такой набор разделов превращает материал из заметки в полноценное практическое руководство по написанию драйверов для FreeBSD.
Контекст публикации показателен для состояния десктопного сегмента FreeBSD: серверные сценарии давно отлажены, тогда как поддержка потребительских ноутбуков нередко упирается в особенности прошивок конкретных производителей. Кнопка питания на современных машинах всё чаще заведена не на классический GPE, а на линии GPIO, и если драйвер GPIO-контроллера или связующий модуль не отрабатывает событие, ядро просто не узнаёт о нажатии. Именно поэтому стандартная настройка hw.acpi.power_button_state в данном случае оказалась бесполезной: событие не доходило до подсистемы ACPI. Автор отдельно оговаривается, что излагает непрофессиональное понимание технологии в объёме, постижимом за две недели, и допускает неточности, приглашая читателей указывать на ошибки в комментариях.
Для российского сообщества FreeBSD материал ценен прежде всего как редкий пример сквозной отладки от пользовательского симптома до собственного модуля ядра. Подобные разборы снижают порог входа для тех, кто хочет разобраться с ACPI и GPIO, но не решается взяться за исходники ядра. Автор подчёркивает, что весь текст набран вручную в LibreOffice без использования больших языковых моделей, и предлагает проверять на нём детекторы сгенерированного контента; публикация распространяется под лицензией CC-BY-SA-4.0 и доступна также в PDF для офлайн-чтения. Сравнивать gpiopwrb с готовыми альтернативами сложно: универсального решения для таких случаев в базовой поставке нет, и каждому придётся либо патчить DSDT, либо писать собственный модуль под конкретную модель ноутбука. Открытым остаётся вопрос, будет ли наработка оформлена как порт или отправлена в upstream FreeBSD, и затронет ли исправление другие модели с аналогичной схемой подключения кнопки питания через GPIO. Пока же история заканчивается счастливо: коллега получил работающую кнопку Power, а сообщество — подробную карту пути от неработающей клавиши до собственного драйвера ядра.