Микрокод контроллера NVMe SSD можно заменить прямо из работающей Linux-системы, без загрузочных флешек и фирменных программ. Спецификация NVMe закладывает такой механизм в само устройство: две стандартные админ-команды закачивают образ прошивки на накопитель и переносят его в один из слотов. Весь этот механизм открывает консольная утилита nvme-cli, а самое любопытное в нём то, что свежую прошивку на некоторых дисках удаётся активировать даже без перезагрузки сервера. Правда, работает такой приём не на всех устройствах, а цена неосторожности бывает высокой. Дальше по порядку: проверка ревизии и числа слотов, закачка образа, коммит с выбором действия, разбор ошибок контроллера и откат.
Роль прошивки в работе NVMe SSD и главные риски обновления
Прошивка накопителя представляет собой микрокод, которым живёт контроллер диска. Он распределяет команды между чипами флеш-памяти, следит за износом ячеек, управляет кэшем и сборкой мусора. Производители выпускают новые сборки: где-то исправляют зависание под нагрузкой, где-то повышают скорость записи, где-то закрывают уязвимость. Обновление прошивки у NVMe SSD стандартизировано так же жёстко, как команды чтения и записи, поэтому один набор утилит подходит к любому диску.
Ключевая идея стандарта в том, что прошивка хранится не в одном месте, а в отдельных слотах. Стандарт допускает от 1 до 7 слотов, их число зависит от производителя. В каждом слоте лежит копия образа с текстовой ревизией длиной до 8 символов. После включения питания контроллер стартует на активном слоте, а хост может сменить точку старта на другой слот из работающей системы.
Обратная сторона гибкости в том, что обновление заканчивается сбросом контроллера. Во время сброса устройства на мгновение пропадают из системы: пространства имён отсоединяются, смонтированные файловые системы рассыпаются в ошибки ввода-вывода. Сбой питания в момент записи образа в слот и вовсе способен оставить накопитель нерабочим, поэтому перед обновлением нужны резервные копии, источник бесперебойного питания и спокойное окно обслуживания.
Подготовка системы и проверка текущей прошивки через nvme list и id-ctrl
Утилита nvme-cli ставится из репозиториев любого дистрибутива. Версии здесь важны. Ветка 1.x закончилась выпуском 1.16 в ноябре 2021 года. Версия 2.0, переписанная поверх библиотеки libnvme, вышла в апреле 2022 года, дальше последовали 2.16 в ноябре 2025 года, а осенью 2026 года началась ветка 3.x. Синтаксис команд обновления прошивки за это время не менялся, а fw-activate давно служит псевдонимом той же команды, поэтому старые скрипты продолжают работать.
Команда nvme list сканирует дерево sysfs и печатает таблицу: узел устройства, серийный номер, модель, пространство имён, ёмкость, формат и ревизия прошивки в колонке FW Rev. Подробности достаются командой nvme id-ctrl, которая запрашивает структуру Identify Controller: поле fr хранит ревизию активной прошивки, поле frmw описывает слоты, поле oacs подтверждает поддержку обновления, поле fwug сообщает о кратности порций. Всё это удобно фильтровать одной строкой:
nvme list
nvme id-ctrl /dev/nvme0 | grep -i -E "^(fr|frmw|fwug|oacs)"
cat /sys/class/nvme/nvme0/firmware_rev
Последняя строка примера читает атрибут sysfs напрямую, ядро дублирует там ревизию активной прошивки. Поле frmw отвечает на большинство практических вопросов. Бит 0 сообщает, защищён ли первый слот от записи. Биты с 1 по 3 кодируют число слотов прошивки. Бит 4 обозначает поддержку активации без перезагрузки, бит 5 добавляет обнаружение множественных обновлений. Например, значение 0x16 это двоичное 10110: 3 слота, активация без перезагрузки есть, первый слот доступен на запись. Значение 0x0A означает уже 5 слотов без поддержки мгновенной активации, что характерно для многих массовых дисков.
Бит 2 в поле oacs подтверждает поддержку пары команд Firmware Download и Firmware Commit. Команды fw-download, fw-commit, fw-log и id-ctrl принимают и символьный узел контроллера /dev/nvme0, и блочный узел пространства имён /dev/nvme0n1, а вот nvme reset требует именно символьный узел.
Скачивание образа командой nvme fw-download и размер передач
Скачивание выглядит незатейливо:
nvme fw-download /dev/nvme0 --fw=/path/to/nvme.fw --xfer=0x20000
Ключ --fw задаёт путь к файлу образа, он обязателен. Ключ --xfer определяет, какими порциями утилита станет отправлять данные, по умолчанию берётся 4 КиБ. Ключ --offset указывает смещение в dwords, по 4 байта каждый, для передачи образа частями. Значение 0x20000 из примера это 128 КиБ за одну передачу.
Образ на 64 МБ состоит из 65 536 КиБ, значит при порциях по 128 КиБ утилита выполнит 512 передач, а при значениях по умолчанию целых 16 384. Части разрешено отправлять даже не по порядку, лишь бы диапазоны dwords не перекрывались. Если вторая порция должна начинаться с отметки 128 КиБ, смещение считается как 131 072 байта, делённые на 4, то есть 32 768 dwords, или 0x8000.
Во время закачки накопитель продолжает обслуживать обычные команды ввода-вывода: стандарт прямо разрешает отправлять fw-download при незавершённых операциях в очередях. Ничего при этом не активируется, образ копируется в память контроллера, и до коммита диск работает на старой версии. С полем fwug стоит свериться заранее: если оно отлично от нуля и от значения FFh, размер порций разумно делать кратным fwug, умноженному на 4 КиБ, иначе контроллер вправе отвергнуть передачу.
Слоты прошивки и ключи активации в nvme fw-commit
Второй шаг делает команда fw-commit, и в ней спрятана вся логика обновления:
nvme fw-commit /dev/nvme0 --slot=1 --action=2
Ключ --slot выбирает слот от 1 до 7, значение 0 отдает выбор контроллеру. Ключ --action определяет, что произойдёт со скачанным образом и слотами. Со значением 0 утилита записывает образ в выбранный слот и ничего не активирует. Значение 1 записывает образ в слот и активирует его при следующем reset. Значение 2 активирует при следующем reset образ, уже лежащий в заданном слоте. Значение 3 просит активировать образ из слота немедленно, без перезагрузки. Значения 6 и 7 работают с загрузочным разделом boot partition: первое заливает скачанный образ в раздел с номером из ключа --bpid, второе помечает раздел активным и обновляет поле BPINFO.ABPID.
Типовой цикл прост: fw-download кладёт образ в память, fw-commit с action 1 переносит его в свободный слот, после сброса диск стартует на новой версии. Прежняя прошивка при этом остаётся лежать в соседнем слоте нетронутой, и откат превращается в одну короткую команду с action 2.
nvme-cli сам контроллер после коммита не перезапускает. Для action 1 или 2 сброс выполняет хост, самый короткий путь проходит через sysfs:
echo 1 > /sys/class/nvme/nvme0/device/reset
Эквивалент это команда nvme reset /dev/nvme0, она запрашивает сброс контроллера и дожидается возвращения в строй.
Активация без перезагрузки и возвращаемые ошибки контроллера
Значение action 3 давно считается самым интригующим. Контроллер с битом активации без перезагрузки в поле frmw готов заменить работающий образ на лету: команды продолжают исполняться, диск не исчезает из системы, простой равен нулю. Для серверов, где NVMe SSD держит базу данных, это целое сокровище: перезагрузка ради прошивки может потребовать переезда десятков виртуальных машин.
Чаще, впрочем, вместо мгновенного успеха приходит статус 0Bh, Firmware Activation Requires Conventional Reset. Коммит при этом принят, а активировать образ контроллер соглашается только через обычный reset. Это не сбой, а штатная реакция, дальше действуют через action 1 и перезагрузку в удобное окно. Стандарт описывает для Firmware Commit полный набор таких ответов. Код 06h, Invalid Firmware Slot, означает, что слот неверен или защищён от записи. Код 07h, Invalid Firmware Image, означает, что образ не распознан, чаще всего это прошивка от другой модели. Коды 10h и 11h требуют сброса NVM-подсистемы или контроллера соответственно. Код 12h, Firmware Activation Requires Maximum Time Violation, сообщает, что мгновенная активация выйдет за пределы MTFA, предельного времени смены образа. Код 13h, Firmware Activation Prohibited, это вендорский запрет на активацию конкретной версии, а код 14h, Overlapping Range, означает, что скачанные части образа перекрыли друг друга.
Время MTFA накопитель раскрывает в поле mtfa структуры id-ctrl, и образ большого размера может не уложиться в лимит. Реакция на коды 0Bh, 10h и 11h одна: выполнить положенный сброс, а коды 07h и 14h означают, что образ нужно качать заново.
Проверка результата через nvme fw-log и откат к старой версии
Результат проверяют сразу после активации, сначала по журналу слотов:
nvme fw-log /dev/nvme0
Свежие версии утилиты печатают строку "Firmware Log for device" и таблицу fw-log с полем afi и значениями frs1 по frs7. В байте afi младший полубайт показывает активный слот прямо сейчас, старший полубайт указывает слот, который станет активным после следующего reset. Значения frs это ASCII-строки длиной до 8 символов, по сути имена сборок прошивки, а пустые слоты утилита не печатает. Контрольный выстрел: nvme list или nvme id-ctrl с фильтром по полю fr обязаны показать новую ревизию.
Откат строится на той же тройке команд. Если старая версия сохранилась в соседнем слоте, достаточно fw-commit с action 2 по её номеру, после сброса контроллер вернётся на прежнюю сборку. Если слоты были затёрты, старый образ придётся закачать заново через fw-download и активировать через action 0 или 1. С разделами boot partition обходительнее: эта область для кода, с которым накопитель стартует, обычно защищена от записи, действия 6 и 7 применяют строго по инструкциям производителя.
Число слотов у разных моделей отличается: где-то их всего пара, и каждая установка новой версии затирает историю. Фирменные диспетчеры учитывают это сами, а через nvme-cli решение принимает администратор, поэтому список слотов перед коммитом стоит смотреть всегда.
Безопасная процедура обновления и типичные ошибки
Проверенный порядок действий на живом сервере выглядит так:
- убедиться в наличии свежих резервных копий и работающего источника бесперебойного питания;
- обновить nvme-cli до ветки 2.x или новее;
- снять текущую ревизию командами nvme list и nvme id-ctrl и сохранить её в заметки;
- сверить номер сборки прошивки с журналом изменений производителя и убедиться, что образ предназначен именно для этой модели;
- залить образ через nvme fw-download с порциями, согласованными с полем fwug;
- закоммитить образ через nvme fw-commit с --action=1 и свободным слотом;
- выполнить nvme reset /dev/nvme0 или перезагрузить сервер в окно обслуживания;
- проверить активный слот через nvme fw-log и убедиться в новой ревизии через nvme list.
Теперь про грабли, на которые наступают чаще всего. Первая это путаница значений 0 и 1 в ключе --action: сервер перезагружен, а ревизия не поменялась, потому что выбрано значение 0, которое активацию не включает. Вторая касается системного диска: коммит на корневой накопитель посреди рабочего дня роняет смонтированные файловые системы, поэтому загрузочный диск обновляют из однопользовательского режима или при загрузке с другого носителя. Третья ошибка в том, что активная версия перезаписывает единственный слот с прошивкой, тогда откат возможен только повторной закачкой старого образа. Четвёртая связана с надеждой на мгновенную активацию на диске, где бит FAWR не установлен, в этом случае ключ --action=3 закономерно вернёт требование обычного reset.
Во время сброса nvme reset возвращает управление, когда контроллер снова поднимется, но пространства имён заново проходят обнаружение, поэтому скрипты автоматизации удобно строить на выводе nvme list -o json, который легко разбирается программно. Дисковые очереди в этот момент обязаны простаивать.
Обновление прошивки NVMe SSD в Linux разрушило миф, что микрокод накопителя требует фирменных программ и отдельной машины. Пара admin-команд из спецификации, консольная утилита и слоты с копиями старых версий дают всю необходимую гибкость: образ можно закачать заранее, активировать в нужное окно, откатиться на соседний слот при первом же подозрении. Слоты прошивки и есть та встроенная страховка, которую замечают лишь тогда, когда нужно вернуться на предыдущую сборку, и именно она превращает обновление из лотереи в плановую операцию.