Отнюдь, проблема именно в С, а точнее, в несовместимости С с потоковой крупномасштабной коммерческой разработкой. Язык для своей ниши требует слишком высокой дисциплины от всех участников процесса, а дисциплину эту настолько высокую практически невозможно обеспечить, потому что это самое обеспечение требует несовместимых с реальностью затрат времени.
Вот хороший пример кода на С, обмазанного достаточным количеством кода на AstraVer для того, чтобы доказать его корректность. Написание всего этого кода (весь проект — гарантированно безопасный загрузчик PE-образов для UEFI) заняло у двух не самых глупых товарищей полгода, а я такой же загрузчик на том же С (но уже без каких-либо гарантий, кроме «от фаззинга не падает» и «мамой клянусь») написал в 2016 году за три дня. В итоге программировать на С так, чтобы гарантировать отсутсвие ошибок, могут себе позволить только те, кто сидит на финансировании из бюджета, и потому по времени практически не ограничен, а коммерческие компании вынуждены бежать, сломя голову, только чтобы на своем месте оставаться, и потому практически весь их код на С не выдерживает никакой критики с точки зрения безопасности.
В итоге недостатки слишком много позволяющего языка пытаются чинить в железе, уже занесли туда теневой стек (Intel CET), подписывание указателей (ARM PAC), тегирование памяти (ARM MTE), и теперь работают над заносом туда же контрактов, которые будет расставлять компилятор, потому что программиста это делать невозможно заставить (CHERI).
Понятно, что для микроконтроллеров, к которых вся прошивка — это конечный автомат на десяток состояний, это все не нужно, и там можно продолжать писать на С спокойно, потому что вся программа влезает в голову одного инженера. Проблемы начинаются там, где в программе уже больше миллиона строк кода, и над ней работает сотня-другая людей непрерывно. Именно там становятся нужны любые возможные способы обеспечить локальность эффектов, предотвратить ошибку до того, как она попала в репозиторий, остановить разработчика от необдуманных поступков вроде создания гонки по данным и передачи данных в соседний поток без использования примитивов синхронизации, т.е. в конце концов именно там мы приходим к необходимости языков вроде Rust.
Короче, если у вас пока что на С все работает и жрать не просит — смело продолжайте на нем писать. А у нас вот давно уже от С геморрой сплошной, а заменить его толком не на что, потому что C++ — это такое же хтоническое чудовище, вид сбоку, а внедрение Rust пока буксует по экономическим причинам (дорого переучивать всю ораву, дорого писать клей, дорого переписывать то, что не получилось приклеить, а дело делать надо уже сейчас).
Ничего себе, а Хабр то, видимо, снова торт!
Спасибо огромное за эту серию статей, потому что теперь есть куда послать интересующихся или сомневающихся русскоязычных товарищей, которых раньше приходилось слать в статьи Фамы и Френча, переведенные автоматикой.
Виртуальную машину EBC наконец-то выкинули (точнее, сделали опциональной, но это по факту выкинули) в UEFI 2.8. Причин этому много, основная — практически ничего на EBC так и не написали, потому что и ВМ сама по себе получилась медленная, глупая, и компилятор для нее Интел зажала открывать и требовала за него деньги, а на ассемблере писать хоть и можно стало рано или поздно благодаря стараниям энтузиастов, но дураков писать на нем драйверы не нашлось. До 2018 года UEFI реально работала только на х86, и потому никаких причин собирать драйвер в EBC, чтобы он запускался на разных архитектурах, у корпораций не было.
Прошивка никогда не будет делить драйверы для какого-то нетривиального оборудования с полноценной ОС, потому что объем поддерживаемых фич у ОРОМа и драйвера из ОС несравнимый. Драйверу графической карты для UEFI («видеобиосу») нужен, по сути, только фреймбуфер (исключения вроде CoreEG2 у Apple, в котором 42 функции и который поддерживает 3d-ускорение ради того, чтобы recoveryOS не выглядела убого, из за чего некоторым картам приходится шить специальные видеобиосы, редки, и потому я их рассматривать тут не стану), а в ОС уже нужен полноценный драйвер. Замечали тот факт, что видеобиос занимает 128\256\512кб, а видеодрайвер — 200мб? Ну вот поэтому универсальных драйверов и нет — они нафиг не нужны, и задачи сделать их таковыми никогда не ставилось.
Что плохого в переключателе я уже выше пояснил: простой пользователь его боится, а назначение его кому-либо, кроме энтузиастов, практически невозможно пояснить. Подавляющее большинство обычных людей даже не знают, что у них там прошивка какая-то вообще есть в компьютере, для чего она нужна и кому, они открывают крышку ноутбука и видят перед собой экран входа в систему. Вся внутренняя кухня этому пользователю активно не интересна, и он из множества вариантов выберет тот, у которого никакие непонятные ручечки крутить не нужно, и непонятные кнопочки нажимать. Пользователь пришел работать и развлекаться, а не принимать решения о запрете\разрешении обновления прошивки. Для энтузиастов же уже сейчас есть возможность купить у purism систему с нужными физическими переключателями, потому что производитель этот — именно на них в качестве своей целевой аудитории и ориентируется, и берет за это вполне осязаемые дополнительные деньги, потому что энтузиастов таковых не много, и больше их не становится.
Про Dell ничего такого не помню, но они использую AMI AptioV на десктопах и серверах, так что вполне могли использовать тот же самый уязвимый код и не заметить.
Они этот кусок используют как признак manufacturing mode, и в этом самом режиме отключают много чего, в том числе и проверку хеша DXE-тома. Позор это, или дизайн такой — мне не ведомо, но на самых новых машинах вроде бы исправили уже.
Еще более смешной баг был у AMI, эти отмочили следующее: драйвер BootGuardPei, накрытый BG вместе со всем остальным PEI-томом и хешами, действительно успешно проверял хеши DXE-тома, только вот при несовпадении он не отключал машину и не переводил ее в режим восстановления прошивки, а создавал HOB с одним байтом, чтобы потом BootGuardDxe уже показал пользователю нужный UI и занимался восстановлением уже из DXE. Я когда это осознал — ржал минут десять, а потом пошел и удалил весь BootGuardDxe, и все ожидаемо заработало.
Какие IBV, такие и цепочки доверия, и даже если сам по себе BG может быть настроен идеально, он покрывает только первое звено, а второе может быть любого качества, в том числе и вот такого.
Я считаю, что это честно в определенном смысле, потому что обманутые ожидания хуже отсутствия таковых. Вся большая четверка азиатских ОЕМов (Asus, Gigabyte, MSI, Asrock) на своих десктопных платах BootGuard не настраивает специально, оставляя простор для модификации прошивок энтузиастами, и потому купить десктопную плату с BG — это целый отдельный квест. С другой стороны этих баррикад у нас Lenovo, которая якобы заботится о безопасности, и якобы настраивает BG, и даже почти перестала косячить с его настройками, но потом выясняется, что проверка DXE-тома отключается одним битом после сигнатуры LNVBBSEC, а сама эта сигнатура лежит в свободном месте тома с NVRAM, который даже PRRами не накрыт. Вот такой BG — хуже, чем никакого.
Главное чтобы его немедленно не откопали IBV, и не начали продавать как value-add, хвалясь совместимостью их новейших систем с MSDOS 6.22 и Windows ME…
И опять у нас в комментариях теории заговора против открытых систем, и отличные-отличные идеи поставить физический переключатель, и забыть о проблемах (и об обновлениях тоже).
Не люблю цитировать сам себя, но придется:
Необходимость двигать тумблер сразу же лишает возможности автоматического обновления прошивки, а т.к. там десяток мегабайт кода (после распаковки), который из крупных кусков кода на С и Ассемблере разных производителей низкооплачиваемые азиатские инженеры собрали на скотч и отборный мат, то в таком коде неизбежны баги, и их очень хочется починить таким образом, чтобы пользователю для этого ничего делать не пришлось. Именно для этого у нас сейчас обновления прошивки ставятся через ESRT прямо из Windows Update и Linux Vendor Firmware Service так же, как и обновления драйверов и остального софта. Просто прошивка современного ПК и сервера — давно уже намного более software, чем firmware, там сетевой стек от FreeBSD, драйверы для FAT32 и NTFS, и OpenGL в BIOS Setup. А сделаешь тумблер — и все, никаких тебе автоматических обновлений, потому что у пользователя лапки, и никакие тумблеры он переключать не будет, потому что боится, потому что сложно, и потому что «лошадь в ванне с огурцами.жпг».
И тумблер WE/RO, и резервирование, и несколько микросхем физически — все это делается давно и успешно на промышленной электронике, обслуживаемой профессионалами за деньги. А тут у нас домашняя электроника, которую пользователь боится больше, чем она его, и потому все подобные начинания будут немедленно зарезаны отделом дизайна и отделом маркетинга у всех компаний, ориентирующихся не на энтузиастов. Для остальных есть ребята типа Purism и system76, у которых там и прошивки все открытые, и тумблер они могут поставить легко, если их убедить в том, что с тумблером их целевая аудитория энтузиастов купит больше их продукции.
По некоторым данным иногда все-же запускается, но на полутора платах с двумя с половиной древними версиями прошивки, которые, скорее всего, просто CSM не полностью отключают.
Действительно на удивление хорошо получилось, пользуюсь давно, привык, удивляться уже перестал. Пользуюсь MBP 13" на M1, и он быстрый, холодный, тихий даже при высокой постоянной нагрузке, держит батарею по два дня, и при этом на нем практически все, чем я пользуюсь, работает быстрее, чем на рабочем MBP 16" на i9 с конфигурацией дороже вчетверо.
Другие ОСи там обязательно заведут (возможность запускать свой код вместо ядра XNU имеется), но непонятно, насколько хорошо они там заработают на голом железе, с учетом того что документации открытой нет, и драйверы придется писать по результатам реверса. Да и не очень понятно, зачем оно все, если виртуализация уже сейчас работает достаточно хорошо и быстро из коробки, Linux запускается без проблем, Windows для ARM тоже завели теперь.
Тяжелый был год, перешли на другую архитектуру, значительно переделали SecureBoot, теперь вот без остановки ловим и чиним баги, плюс еще удаленка, из за которой не работаешь из дома, а живешь на работе. Некогда в итоге писать, да и не хочется особо.
Пожалуйста. Вообще статья получилась плюс-минус «обо всем и не о чем», но в качестве иллюстрации к тому, что надо бы сначала версию выяснить, а потом идти код смотреть — пойдет.
Error: success, особенно если это был errno — весьма популярная ситуация даже у тех, кто на C давно пишет, да и сама по себе идея errno довольно глупая (потому что одна глобальная переменная без каких-либо метаданных о том, кто ее выставил и когда — это, скажем так, недостаточно), но теперь уже никто исправлять стандартную библиотеку не станет, поэтому приходится жить с этим всем.
Обратите внимание на пятый коммутатор прямо рядом с M.2-слотом, и на вот эту ремарку на сайте самой платы: *If PCIE5 slot is occupied, M2_2 will be disabled. Чуете подвох?
Там отдают либо все 16 линий в один слот, если один занят, а второй — нет, или по 8 на оба, поэтому и приходится активничать. Можно, конечно, поставить тумблер и дать все это коммутировать вручную, но пользователь нынче балованный и такую фигню терпеть не будет.
Устройства эти пассивные (и тупые как пробка, управляются одним выводом SEL), в дереве их не увидеть.
Эти пять коммутаторов — они не для чипсета, они как раз для тех двадцати дифференциальных пар, которые идут непосредственно от CPU. Почему их ставят: так дешевле, чем встраивать коммутацию в процессор (придется тащить вдвое больше линий от него), поэтому коммутируют уже на месте.
Мне кажется, мы тут несколько не договорились о терминологии, и потому называем «коммутатором» разные устройства. Вот эти вот — тупые физические переключалки туда-сюда, а не хитрые умножители одной линии на 4, со своим PCIe-адресом, прошивкой, роутером и перепаковщиком пакетов.
Тем не менее, если тупой физический переключатель не влезает в тайминги и\или импедансы, нужные для PCIe 4.0, то как 4.0 он не заведется.
Сам нашел в итоге, NXP CBTL04083B, 3.3 V, 4 differential channel, 2: 1 multiplexer/demultiplexer switch for PCI Express Gen3. Будет ли он работать с PCIe 4.0 — одному рандому известно, производитель ничего не гарантирует.
Вот хороший пример кода на С, обмазанного достаточным количеством кода на AstraVer для того, чтобы доказать его корректность. Написание всего этого кода (весь проект — гарантированно безопасный загрузчик PE-образов для UEFI) заняло у двух не самых глупых товарищей полгода, а я такой же загрузчик на том же С (но уже без каких-либо гарантий, кроме «от фаззинга не падает» и «мамой клянусь») написал в 2016 году за три дня. В итоге программировать на С так, чтобы гарантировать отсутсвие ошибок, могут себе позволить только те, кто сидит на финансировании из бюджета, и потому по времени практически не ограничен, а коммерческие компании вынуждены бежать, сломя голову, только чтобы на своем месте оставаться, и потому практически весь их код на С не выдерживает никакой критики с точки зрения безопасности.
В итоге недостатки слишком много позволяющего языка пытаются чинить в железе, уже занесли туда теневой стек (Intel CET), подписывание указателей (ARM PAC), тегирование памяти (ARM MTE), и теперь работают над заносом туда же контрактов, которые будет расставлять компилятор, потому что программиста это делать невозможно заставить (CHERI).
Понятно, что для микроконтроллеров, к которых вся прошивка — это конечный автомат на десяток состояний, это все не нужно, и там можно продолжать писать на С спокойно, потому что вся программа влезает в голову одного инженера. Проблемы начинаются там, где в программе уже больше миллиона строк кода, и над ней работает сотня-другая людей непрерывно. Именно там становятся нужны любые возможные способы обеспечить локальность эффектов, предотвратить ошибку до того, как она попала в репозиторий, остановить разработчика от необдуманных поступков вроде создания гонки по данным и передачи данных в соседний поток без использования примитивов синхронизации, т.е. в конце концов именно там мы приходим к необходимости языков вроде Rust.
Короче, если у вас пока что на С все работает и жрать не просит — смело продолжайте на нем писать. А у нас вот давно уже от С геморрой сплошной, а заменить его толком не на что, потому что C++ — это такое же хтоническое чудовище, вид сбоку, а внедрение Rust пока буксует по экономическим причинам (дорого переучивать всю ораву, дорого писать клей, дорого переписывать то, что не получилось приклеить, а дело делать надо уже сейчас).
Спасибо огромное за эту серию статей, потому что теперь есть куда послать интересующихся или сомневающихся русскоязычных товарищей, которых раньше приходилось слать в статьи Фамы и Френча, переведенные автоматикой.
Прошивка никогда не будет делить драйверы для какого-то нетривиального оборудования с полноценной ОС, потому что объем поддерживаемых фич у ОРОМа и драйвера из ОС несравнимый. Драйверу графической карты для UEFI («видеобиосу») нужен, по сути, только фреймбуфер (исключения вроде CoreEG2 у Apple, в котором 42 функции и который поддерживает 3d-ускорение ради того, чтобы recoveryOS не выглядела убого, из за чего некоторым картам приходится шить специальные видеобиосы, редки, и потому я их рассматривать тут не стану), а в ОС уже нужен полноценный драйвер. Замечали тот факт, что видеобиос занимает 128\256\512кб, а видеодрайвер — 200мб? Ну вот поэтому универсальных драйверов и нет — они нафиг не нужны, и задачи сделать их таковыми никогда не ставилось.
Что плохого в переключателе я уже выше пояснил: простой пользователь его боится, а назначение его кому-либо, кроме энтузиастов, практически невозможно пояснить. Подавляющее большинство обычных людей даже не знают, что у них там прошивка какая-то вообще есть в компьютере, для чего она нужна и кому, они открывают крышку ноутбука и видят перед собой экран входа в систему. Вся внутренняя кухня этому пользователю активно не интересна, и он из множества вариантов выберет тот, у которого никакие непонятные ручечки крутить не нужно, и непонятные кнопочки нажимать. Пользователь пришел работать и развлекаться, а не принимать решения о запрете\разрешении обновления прошивки. Для энтузиастов же уже сейчас есть возможность купить у purism систему с нужными физическими переключателями, потому что производитель этот — именно на них в качестве своей целевой аудитории и ориентируется, и берет за это вполне осязаемые дополнительные деньги, потому что энтузиастов таковых не много, и больше их не становится.
Еще более смешной баг был у AMI, эти отмочили следующее: драйвер BootGuardPei, накрытый BG вместе со всем остальным PEI-томом и хешами, действительно успешно проверял хеши DXE-тома, только вот при несовпадении он не отключал машину и не переводил ее в режим восстановления прошивки, а создавал HOB с одним байтом, чтобы потом BootGuardDxe уже показал пользователю нужный UI и занимался восстановлением уже из DXE. Я когда это осознал — ржал минут десять, а потом пошел и удалил весь BootGuardDxe, и все ожидаемо заработало.
Какие IBV, такие и цепочки доверия, и даже если сам по себе BG может быть настроен идеально, он покрывает только первое звено, а второе может быть любого качества, в том числе и вот такого.
Заодно могу порекомендовать вот эту презентацию об относительно недавней TOCTOU-атаке на Boot Guard, из которой я взял картинку выше.
Не люблю цитировать сам себя, но придется:
Другие ОСи там обязательно заведут (возможность запускать свой код вместо ядра XNU имеется), но непонятно, насколько хорошо они там заработают на голом железе, с учетом того что документации открытой нет, и драйверы придется писать по результатам реверса. Да и не очень понятно, зачем оно все, если виртуализация уже сейчас работает достаточно хорошо и быстро из коробки, Linux запускается без проблем, Windows для ARM тоже завели теперь.
Error: success, особенно если это был errno — весьма популярная ситуация даже у тех, кто на C давно пишет, да и сама по себе идея errno довольно глупая (потому что одна глобальная переменная без каких-либо метаданных о том, кто ее выставил и когда — это, скажем так, недостаточно), но теперь уже никто исправлять стандартную библиотеку не станет, поэтому приходится жить с этим всем.
Эти пять коммутаторов — они не для чипсета, они как раз для тех двадцати дифференциальных пар, которые идут непосредственно от CPU. Почему их ставят: так дешевле, чем встраивать коммутацию в процессор (придется тащить вдвое больше линий от него), поэтому коммутируют уже на месте.
Мне кажется, мы тут несколько не договорились о терминологии, и потому называем «коммутатором» разные устройства. Вот эти вот — тупые физические переключалки туда-сюда, а не хитрые умножители одной линии на 4, со своим PCIe-адресом, прошивкой, роутером и перепаковщиком пакетов.
Тем не менее, если тупой физический переключатель не влезает в тайминги и\или импедансы, нужные для PCIe 4.0, то как 4.0 он не заведется.