Limine protocol
Протокол загрузки Limine
Протокол загрузки Limine - это современный, переносимый, многофункциональный и расширяемый загрузочный протокол.
Данный файл служит спецификацией протокола и официальным централизованным сборником возможностей (features), из которых состоит загрузочный протокол Limine.
Загрузчики могут поддерживать дополнительные неофициальные возможности, однако настоятельно рекомендуется избегать фрагментации и предлагать новые возможности, открывая pull request в репозиторий limine-protocol на Codeberg.
Файл limine.h предоставляет реализацию всех структур и констант, описанных в этом документе, для языков C и C++.
Содержание
Общие замечания
«Исполняемый файл» - это ядро или иное автономное приложение, загружаемое совместимым с протоколом Limine загрузчиком.
Протокол Limine не навязывает использование какого-либо конкретного формата исполняемого двоичного файла, хотя формат ELF настоятельно рекомендуется.
Поддерживаются только 64-битные машины с прямым (little-endian) порядком байтов.
Все указатели имеют ширину 64 бита. Все ненулевые указатели указывают на объект с уже прибавленным смещением прямого отображения старшей половины адресного пространства (Higher Half Direct Map, HHDM), если не указано иное.
Все ответы и связанные с ними структуры данных размещаются в регионах памяти, возвращаемых загрузчику (bootloader-reclaimable).
Протокол использует и ожидает от исполняемого файла следующие ABI:
-
x86-64: System V ABI без FP/SIMD
-
aarch64: AAPCS64 без FP/SIMD
-
riscv64: LP64 (soft-float)
-
loongarch64: LP64S (soft-float)
Исполняемый файл может использовать FP/SIMD внутри себя, но при взаимодействии с протоколом загрузки Limine должны соблюдаться указанные ABI.
Разделители запросов
Загрузчик может быть проинструктирован начать и/или прекратить поиск запросов (включая теги базовых ревизий) в загруженном образе исполняемого файла путём размещения маркеров начала и/или конца на границе, выровненной по 8 байтам.
Загрузчик будет принимать запросы только между последним найденным маркером начала (если таких больше одного, чего в идеале быть не должно) и первым найденным маркером конца.
#define LIMINE_REQUESTS_START_MARKER { 0xf6b8f4b39de7d1ae, 0xfab91a6940fcb9cf, \
0x785c6ed015d3e316, 0x181e920a7852b9d9 }
#define LIMINE_REQUESTS_END_MARKER { 0xadc0e0531bb10d03, 0x9572709f31764c62 }
Для базовых ревизий 0 и 1 разделители запросов являются подсказками. Загрузчик может продолжать поиск запросов и тегов базовых ревизий за пределами указанной области, если он не поддерживает такие подсказки.
Единственное отличие базовой ревизии 2 от базовой ревизии 1 заключается в том, что поддержка разделителей запросов обязательна, и разделители должны соблюдаться, если присутствуют, а не просто рассматриваться как подсказка.
Секция запросов Limine
⚠️ ВНИМАНИЕ
Это поведение устарело и удалено начиная с базовой ревизии 1.
Для исполняемых файлов, запрашивающих устаревшую базовую ревизию 0, если исполняемый файл содержит исполняемую секцию .limine_reqs, загрузчик вместо сканирования всего образа исполняемого файла на предмет запросов будет извлекать запросы из завершённого нулём массива указателей на предоставленные запросы, содержащегося в указанной секции.
Базовые ревизии
Протокол загрузки Limine существует в нескольких базовых ревизиях; на данный момент определено 5 базовых ревизий: от 0 до 4.
Базовые ревизии изменяют определённое поведение протокола Limine вне каких-либо конкретных возможностей. Подробности будут описаны по мере необходимости в этой спецификации, а также объединены в разделе Сводка изменений базовых ревизий.
Базовые ревизии с 0 по 3 считаются устаревшими.
Базовая ревизия 0 является ревизией по умолчанию, которую исполняемый файл считается запрашивающим и соответствующей, если исполняемый файл не предоставляет тег базовой ревизии, что обеспечивает обратную совместимость.
Тег базовой ревизии - это набор из трёх 64-битных значений, размещенных где-то в загруженном образе исполняемого файла на границе, выровненной по 8 байтам; первые два значения - магическое число, позволяющее загрузчику идентифицировать тег, а последнее значение - запрошенный номер базовой ревизии.
#define LIMINE_BASE_REVISION(N) { 0xf9562b2d5c95a6c8, 0x6a7b384944536bdc, (N) }
Если загрузчик прекращает поддержку более старой базовой ревизии, он должен отказать в загрузке исполняемого файла, запрашивающего такую базовую ревизию. Если загрузчик ещё не поддерживает запрошенную базовую ревизию (т.е. запрошенная базовая ревизия выше максимальной поддерживаемой), он должен загрузить исполняемый файл с использованием любой произвольной ревизии, которую он поддерживает, и сообщить об отказе в соответствии с исполняемым файлом, оставив третий компонент тега базовой ревизии без изменений.
С другой стороны, если запрошенная исполняемым файлом базовая ревизия поддерживается, третий компонент тега базовой ревизии должен быть установлен в 0 загрузчиком.
ℹ️ ПРИМЕЧАНИЕ
Это означает, что в отличие от случая, когда загрузчик прекращает поддержку более старой базовой ревизии и сам отвечает за отказ в загрузке исполняемого файла, в случае, когда загрузчик ещё не поддерживает запрошенную исполняемым файлом базовую ревизию, исполняемый файл сам должен завершить работу с ошибкой (или иным образом обработать это условие).
Для любого совместимого с Limine загрузчика, поддерживающего базовую ревизию 3 или выше, обязательно:
-
загружать исполняемые файлы, запрашивающие более высокие неподдерживаемые ревизии, минимум с базовой ревизией 3;
-
всегда устанавливать второй компонент тега базовой ревизии в фактически используемую базовую ревизию, независимо от того, была ли она запрошена или нет.
#define LIMINE_BASE_REVISION_SUPPORTED(VAR) ((VAR)[2] == 0)
#define LIMINE_LOADED_BASE_REVISION_VALID(VAR) ((VAR)[1] != 0x6a7b384944536bdc)
#define LIMINE_LOADED_BASE_REVISION(VAR) ((VAR)[1])
Сводка изменений базовых ревизий
Этот раздел объединяет все изменения, внесённые каждой базовой ревизией, для удобства справки.
Базовая ревизия 0
Это ревизия по умолчанию, используемая, если тег базовой ревизии не предоставлен.
-
Поддерживает исполняемую секцию
.limine_reqsдля предоставления списка запросов. -
Разделители запросов (маркеры начала/конца) рассматриваются только как подсказки.
-
Доступно тождественное отображение (начиная со смещения
0x1000). -
HHDM (прямое отображение старшей половины адресного пространства) охватывает все регионы карты памяти.
-
Память между
0и0x1000никогда не помечается как используемая в карте памяти. -
aarch64:
TTBR0_EL1указывает на таблицы страниц тождественного отображения, предоставленные загрузчиком.
Базовая ревизия 1
Изменения по сравнению с базовой ревизией 0:
-
Отменена поддержка метода поиска запросов через исполняемую секцию
.limine_reqs. -
Удалено тождественное отображение.
-
Отображения HHDM больше не включают регионы карты памяти типов:
-
Зарезервированная (
Reserved) -
Ненадёжная память (
Bad memory) -
aarch64:
TTBR0_EL1теперь не определён и может свободно использоваться исполняемым файлом. -
Разделители запросов по-прежнему являются только подсказками.
Базовая ревизия 2
Изменения по сравнению с базовой ревизией 1:
-
Разделители запросов теперь должны соблюдаться, если присутствуют (больше не являются необязательными подсказками).
-
Всё остальное поведение остаётся таким же, как в базовой ревизии 1.
Базовая ревизия 3
Изменения по сравнению с базовой ревизией 2:
-
Отображение HHDM становится ограничительным - отображаются только следующие регионы карты памяти:
-
Используемая (
Usable) -
Возвращаемая загрузчику (
Bootloader reclaimable) -
Исполняемый файл и модули (
Executable and modules) -
Фреймбуфер (
Framebuffer) -
Удалено безусловное прямое отображение первых 4 ГиБ памяти в прямое отображение старшей половины адресного пространства (Higher Half Direct Map).
-
Память между
0и0x1000теперь может быть помечена как используемая в карте памяти. -
Адрес RSDP возвращается как физический (только базовая ревизия 3).
-
Адреса точек входа SMBIOS возвращаются как физические.
-
Адрес таблицы системы EFI возвращается как физический.
-
Требование к загрузчику: должен поддерживать загрузку исполняемых файлов, запрашивающих более высокие неподдерживаемые ревизии, минимум с базовой ревизией 3.
-
Требование к загрузчику: должен устанавливать второй компонент тега базовой ревизии в фактически используемую базовую ревизию.
Базовая ревизия 4
Изменения по сравнению с базовой ревизией 3:
-
HHDM дополнительно отображает следующие регионы карты памяти:
-
Таблицы ACPI (
ACPI tables) -
Восстанавливаемая память ACPI (
ACPI reclaimable) -
Неволатильное хранилище ACPI (
ACPI NVS) -
Добавлен новый тип региона карты памяти:
LIMINE_MEMMAP_ACPI_TABLES. -
Гарантируется, что таблицы ACPI (RSDP, RSDT, XSDT, все таблицы, на которые указывают RSDT и XSDT, FACS, X_FACS, DSDT, X_DSDT) отображены внутри любого из регионов ACPI в карте памяти.
-
Адрес RSDP снова возвращается как виртуальный (HHDM) (только в базовой ревизии 3 возвращался как физический).
-
aarch64:
-
MAIR_EL1.Attr0гарантированно равен0xff(Normal Write-Back RW-Allocate non-transient). -
MAIR_EL1.Attr1гарантированно имеет правильный тип кэширования для фреймбуфера. -
Все остальные записи
MAIR_EL1гарантированно не используются, если не указано иное в запросе (на данный момент таких запросов не определено).
Компоновка памяти при передаче управления
Протокол требует, чтобы исполняемые файлы загружались по адресу 0xffffffff80000000 или выше. Исполняемые файлы, загружаемые в младшую половину адресного пространства, не поддерживаются. Для перемещаемых исполняемых файлов, запрашивающих загрузку по адресу 0, применяется минимальное смещение (slide) 0xffffffff80000000.
При передаче управления исполняемый файл будет надлежащим образом загружен и отображён с соответствующими правами MMU в режиме супервизора по запрошенному виртуальному адресу (при условии, что он находится по адресу 0xffffffff80000000 или выше).
Конкретное физическое размещение памяти не гарантируется, за исключением того, что загруженный образ исполняемого файла гарантированно физически непрерывен. Чтобы определить, где исполняемый файл загружен в физической памяти, см. Возможность адреса исполняемого файла.
Наряду с загруженным исполняемым файлом загрузчик настраивает отображения памяти следующим образом:
| Базовый физический адрес | | Базовый виртуальный адрес |
|--------------------------|-------------------------------|---------------------------|
| 0x0000000000001000 | (4 ГиБ - 0x1000) и любые дополнительные регионы карты памяти | 0x0000000000001000 (только базовая ревизия 0) |
| 0x0000000000000000 | 4 ГиБ и дополнительные регионы карты памяти в зависимости от базовой ревизии | Начало HHDM |
Где «начало HHDM» возвращается возможностью Прямое отображение старшей половины адресного пространства.
Эти отображения предназначены для супервизора и имеют права чтения, записи и выполнения (-rwx).
Когда регион карты памяти отображается в HHDM, для отображений используется минимальный размер страницы 4 КиБ; если начальный или конечный адрес региона не выровнен по 4 КиБ, отображения выходят за границы региона, чтобы выровняться по 4 КиБ, одновременно покрывая весь регион.
Для базовой ревизии 0 вышеупомянутые тождественные отображения выше 4 ГиБ и HHDM охватывают любой регион карты памяти.
Для базовых ревизий 1 и 2 отображения HHDM выше 4 ГиБ не включают регионы карты памяти типов:
-
Зарезервированная (
Reserved) -
Ненадёжная память (
Bad memory)
Для базовой ревизии 3 или выше единственными регионами карты памяти, отображаемыми в HHDM, являются:
-
Используемая (
Usable) -
Возвращаемая загрузчику (
Bootloader reclaimable) -
Исполняемый файл и модули (
Executable and modules) -
Фреймбуфер (
Framebuffer)
Кроме того, безусловное прямое отображение первых 4 ГиБ отменяется, и отображаются только регионы карты памяти соответствующих типов.
Для базовой ревизии 4 или выше дополнительно отображаются следующие регионы в дополнение к тем, которые отображаются в базовой ревизии 3:
-
Таблицы ACPI (
ACPI tables) -
Восстанавливаемая память ACPI (
ACPI reclaimable) -
Неволатильное хранилище ACPI (
ACPI NVS)
Таблицы страниц загрузчика находятся в памяти, возвращаемой загрузчику (см. Возможность карты памяти), и их конкретная компоновка не определена, при условии, что они обеспечивают вышеуказанные отображения памяти.
Если исполняемый файл является позиционно-независимым исполняемым файлом, загрузчик может переместить его по своему усмотрению, потенциально выполняя рандомизацию смещения.
Кэширование
x86-64
Исполняемый файл, загруженный по виртуальному адресу 0xffffffff80000000 или выше, видит все свои сегменты, отображённые с использованием кэширования write-back (WB) на уровне таблиц страниц. Это соответствует PAT[0], если поддерживается PAT.
Все регионы памяти HHDM и тождественного отображения отображаются с использованием кэширования write-back (WB) на уровне таблиц страниц (опять же PAT[0]), за исключением регионов фреймбуфера, которые отображаются с использованием кэширования write-combining (WC) на уровне таблиц страниц (PAT[5], если процессор поддерживает PAT, см. ниже).
Если процессор поддерживает PAT (Page Attribute Table), его компоновка должна быть следующей:
-
PAT0 → WB
-
PAT1 → WT
-
PAT2 → UC-
-
PAT3 → UC
-
PAT4 → WP
-
PAT5 → WC
-
PAT6 → не определено
-
PAT7 → не определено
MTRR остаются такими, какими их настроила прошивка.
aarch64
Исполняемый файл, загруженный по виртуальному адресу 0xffffffff80000000 или выше, видит все свои сегменты, отображённые с использованием режима кэширования Normal Write-Back RW-Allocate non-transient (MAIR_EL1.Attr0).
Все регионы памяти HHDM и тождественного отображения отображаются с использованием режима кэширования Normal Write-Back RW-Allocate non-transient (гарантированно в MAIR_EL1.Attr0 для базовой ревизии 4 или выше), за исключением регионов фреймбуфера, которые отображаются с использованием неопределённого режима кэширования (гарантированно в MAIR_EL1.Attr1 для базовой ревизии 4 или выше), корректного для использования с фреймбуфером на платформе.
Для базовых ревизий < 4 регистр MAIR_EL1 будет как минимум содержать записи для вышеупомянутых режимов кэширования в неопределённом порядке.
Для базовой ревизии 4 и выше MAIR_EL1.Attr0 гарантированно равен 0xff (т.е. режим кэширования Normal Write-Back RW-Allocate non-transient), MAIR_EL1.Attr1 гарантированно является записью, используемой для отображения фреймбуфера, с правильным типом кэширования для него, и все остальные записи в MAIR_EL1 гарантированно не используются, если не указано иное в запросе (на данный момент таких запросов не определено).
riscv64
Исполняемый файл, загруженный по виртуальному адресу 0xffffffff80000000 или выше, и все регионы памяти HHDM и тождественного отображения отображаются со значением по умолчанию PBMT=PMA.
Если доступно расширение Svpbmt, все регионы памяти фреймбуфера отображаются со значением PBMT=NC для включения оптимизаций write-combining.
Если расширение Svpbmt недоступно, переопределение PMA невозможно (фактически всё отображается со значением PBMT=PMA).
loongarch64
Исполняемый файл, загруженный по виртуальному адресу 0xffffffff80000000 или выше, видит все свои сегменты, отображённые с использованием типа доступа к памяти Coherent Cached (CC) (MAT).
Все регионы памяти HHDM и тождественного отображения отображаются с использованием типа доступа к памяти Coherent Cached (CC) (MAT), за исключением регионов фреймбуфера, которые отображаются с использованием типа доступа к памяти Weakly-ordered UnCached (WUC) (MAT).
Состояние машины при передаче управления
x86-64
-
ripбудет точкой входа, определённой в формате исполняемого файла, если не запрошена Возможность точки входа, в этом случае значениеripбудет взято оттуда. -
При передаче управления все сегментные регистры загружены как 64-битные сегменты кода/данных, пределы и базы игнорируются, так как это 64-битный режим.
-
Регистр GDT загружен и указывает на GDT в памяти, возвращаемой загрузчику, с как минимум следующими записями, начиная со смещения 0:
-
Нулевой дескриптор
-
16-битный сегмент кода. База =
0, предел =0xffff. Доступен для чтения. -
16-битный сегмент данных. База =
0, предел =0xffff. Доступен для записи. -
32-битный сегмент кода. База =
0, предел =0xffffffff. Доступен для чтения. -
32-битный сегмент данных. База =
0, предел =0xffffffff. Доступен для записи. -
64-битный сегмент кода. База и предел несущественны. Доступен для чтения.
-
64-битный сегмент данных. База и предел несущественны. Доступен для записи.
-
IDT находится в неопределённом состоянии. Исполняемый файл должен загрузить свой собственный.
-
Флаги IF, VM и флаг направления (direction flag) сброшены при передаче управления. Прочие флаги не определены.
-
PG включён (
cr0), PE включён (cr0), PAE включён (cr4), WP включён (cr0), LME включён (EFER). -
NX включён (
EFER), если доступен. -
Если запрошена и доступна страничная адресация 5-го уровня, то включена страничная адресация 5-го уровня (бит LA57 в
cr4). -
Шлюз A20 открыт.
-
Устаревшие IRQ от PIC (если доступен) и IO APIC (только с режимом доставки fixed (0b000) или lowest priority (0b001)) все замаскированы.
-
Если загрузка выполнена через EFI, сервисы загрузки завершены.
-
rspустановлен на вершину стека в памяти, возвращаемой загрузчику, размер которого составляет как минимум 64 КиБ (65536 байт) или размер, указанный в Возможности размера стека. На этот стек перед переходом к точке входа исполняемого файла помещается недопустимый адрес возврата0. -
Все остальные регистры общего назначения (
rax–r15) установлены в0.
aarch64
-
PCбудет точкой входа, определённой в формате исполняемого файла, если не запрошена Возможность точки входа, в этом случае значениеPCбудет взято оттуда. -
Содержимое регистра
VBAR_EL1не определено, и исполняемый файл должен загрузить свой собственный. -
Содержимое регистра
MAIR_EL1описано выше в разделе кэширования. -
Все прерывания замаскированы (
PSTATE.{D, A, I, F}установлены в 1). -
Исполняемый файл получает управление в little-endian AArch64 EL1t (EL1 с
PSTATE.SP, установленным в 0,PSTATE.E, установленным в 0, иPSTATE.nRW, установленным в 0). -
Прочие поля
PSTATEне определены. -
При передаче управления: MMU (
SCTLR_EL1.M) включён, I-Cache и D-Cache (SCTLR_EL1.{I, C}) включены, проверка выравнивания данных (SCTLR_EL1.A) отключена. Проверка выравнивания SP (SCTLR_EL1.{SA, SA0}) включена. Прочие поляSCTLR_EL1сброшены в 0 или в их зарезервированное значение. -
Высшие уровни привилегий не мешают доступу к векторным или операциям с плавающей запятой и регистрам.
-
Высшие уровни привилегий не мешают доступу к универсальному таймеру и счётчику.
-
Используемый размер гранулы трансляции для
TTBR0_EL1иTTBR1_EL1составляет 4 КиБ. -
TCR_EL1.{T0SZ, T1SZ}установлены в 16 при 4-уровневой адресации или в 12 при 5-уровневой адресации. Кроме того, для 5-уровневой адресацииTCR_EL1.DSустановлен в 1. -
TTBR1_EL1указывает на таблицы страниц старшей половины, предоставленные загрузчиком. -
Для базовой ревизии 0
TTBR0_EL1указывает на таблицы страниц тождественного отображения, предоставленные загрузчиком, и не определён для всех остальных базовых ревизий и, следовательно, может свободно использоваться исполняемым файлом. -
Если загрузка выполнена через EFI, сервисы загрузки завершены.
-
SPустановлен на вершину стека в памяти, возвращаемой загрузчику, размер которого составляет как минимум 64 КиБ (65536 байт) или размер, указанный в Возможности размера стека. -
Все остальные регистры общего назначения (включая
X29иX30) установлены в0. -
Векторные регистры находятся в неопределённом состоянии.
riscv64
-
При передаче управления машина работает в режиме супервизора.
-
pcбудет точкой входа, определённой в формате исполняемого файла, если не запрошена Возможность точки входа, в этом случае значениеpcбудет взято оттуда. -
x1(ra) установлен в0, исполняемый файл не должен возвращаться из точки входа. -
x2(sp) установлен на вершину стека в памяти, возвращаемой загрузчику, размер которого составляет как минимум 64 КиБ (65536 байт) или размер, указанный в Возможности размера стека. -
x3(gp) установлен в0, исполняемый файл должен загрузить свой собственный глобальный указатель, если это необходимо. -
Все остальные регистры общего назначения, за исключением
x5(t0), установлены в0. -
Если загрузка выполнена через EFI, сервисы загрузки завершены.
-
stvecнаходится в неопределённом состоянии.sstatus.SIEиsieустановлены в0. -
sstatus.FSиsstatus.XSустановлены вOff. -
Включена страничная адресация с режимом, указанным в Возможности режима страничной адресации.
-
(A)PLIC, если присутствует, находится в неопределённом состоянии.
loongarch64
-
При передаче управления машина работает в PLV0.
-
$pcбудет точкой входа, определённой в формате исполняемого файла, если не запрошена Возможность точки входа, в этом случае значение$pcбудет взято оттуда. -
$r1($ra) установлен в0, исполняемый файл не должен возвращаться из точки входа. -
$r3($sp) установлен на вершину стека в памяти, возвращаемой загрузчику, размер которого составляет как минимум 64 КиБ (65536 байт) или размер, указанный в Возможности размера стека. -
Все остальные регистры общего назначения, за исключением
$r12($t0), установлены в0. -
Если загрузка выполнена через EFI, сервисы загрузки завершены.
-
CSR.EENTRY,CSR.MERRENTRYиCSR.DWM0-3находятся в неопределённом состоянии. -
PGвCSR.CRMDравен 1,DAравен 0,IEравен 0 иPLVравен 0, но в остальном не определён. -
CSR.TLBRENTRYзаполнен предоставленным обработчиком перезагрузки TLB.
Возможности
Протокол основан на концепции запрос/ответ - коллективно называемых «возможностями» - где исполняемый файл запрашивает у загрузчика некоторое действие или информацию, и загрузчик отвечает соответствующим образом, если способен это сделать.
В терминах C возможность состоит из двух структур: запрос и ответ.
Запрос
Запрос имеет 3 обязательных члена в начале структуры:
struct limine_example_request {
uint64_t id[4];
uint64_t revision;
struct limine_example_response *response;
... дополнительные члены следуют ...
};
id- идентификатор запроса. Это выровненное по 8 байтам магическое число, по которому загрузчик сканирует загруженный образ исполняемого файла для поиска запросов. Идентификаторы запросов состоят из 4 64-битных беззнаковых целых чисел, но первые 2 общие для каждого запроса:
#define LIMINE_COMMON_MAGIC 0xc7b1dd30df4c8b88, 0x0a82e883a194f07b
Запросы могут находиться в любом месте загруженного образа исполняемого файла, если они выровнены по 8 байтам. Может быть только один запрос с одинаковым идентификатором. Загрузчик откажет в загрузке исполняемого файла с несколькими запросами с одинаковыми идентификаторами.
-
revision- ревизия запроса, предоставляемая исполняемым файлом. Она начинается с 0 и увеличивается при добавлении новых членов или функциональности в структуру запроса. Загрузчики обрабатывают запросы обратно совместимым образом. Это означает, что если загрузчик не поддерживает ревизию запроса, он обработает запрос так, как если бы это была самая высокая ревизия, поддерживаемая загрузчиком. -
response- это поле заполняется загрузчиком во время загрузки указателем на структуру ответа, если запрос был успешно обработан. Если запрос не поддерживается или не был успешно обработан, это поле остаётся без изменений, то есть если оно было установлено вNULL, оно останется таким.
Ответ
Ответ имеет только 1 обязательный член в начале структуры:
struct limine_example_response {
uint64_t revision;
... дополнительные члены следуют ...
};
revision- как и для запросов, загрузчики помечают ответы номером ревизии. Эта ревизия не связана между запросами и ответами, так как они увеличиваются индивидуально при добавлении новых членов или изменении функциональности. Загрузчики устанавливают ревизию на ту, которую они предоставляют, и это всегда обратно совместимо, то есть более высокие ревизии поддерживают всё, что поддерживают более низкие ревизии.
Это всё, что касается возможностей. Список официальных возможностей Limine приведён в разделе «Список возможностей» ниже.
Список возможностей
Информация о загрузчике
ID:
#define LIMINE_BOOTLOADER_INFO_REQUEST_ID { LIMINE_COMMON_MAGIC, 0xf55038d8e2a1202f, 0x279426fcf5f59740 }
Запрос:
struct limine_bootloader_info_request {
uint64_t id[4];
uint64_t revision;
struct limine_bootloader_info_response *response;
};
Ответ:
struct limine_bootloader_info_response {
uint64_t revision;
char *name;
char *version;
};
name и version - строки ASCII с нулевым завершением, содержащие имя и версию загружающего загрузчика.
Командная строка исполняемого файла
ID:
#define LIMINE_EXECUTABLE_CMDLINE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x4b161536e598651e, 0xb390ad4a2f1f303a }
Запрос:
struct limine_executable_cmdline_request {
uint64_t id[4];
uint64_t revision;
struct limine_executable_cmdline_response *response;
};
Ответ:
struct limine_executable_cmdline_response {
uint64_t revision;
char *cmdline;
};
cmdline - строка ASCII с нулевым завершением, содержащая командную строку, связанную с загружаемым исполняемым файлом. Это указатель на ту же память, что и член string структуры executable_file из Возможности исполняемого файла.
Тип прошивки
ID:
#define LIMINE_FIRMWARE_TYPE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x8c2f75d90bef28a8, 0x7045a4688eac00c3 }
Запрос:
struct limine_firmware_type_request {
uint64_t id[4];
uint64_t revision;
struct limine_firmware_type_response *response;
};
Ответ:
struct limine_firmware_type_response {
uint64_t revision;
uint64_t firmware_type;
};
firmware_type - перечисление, которое может иметь одно из следующих значений:
#define LIMINE_FIRMWARE_TYPE_X86BIOS 0
#define LIMINE_FIRMWARE_TYPE_EFI32 1
#define LIMINE_FIRMWARE_TYPE_EFI64 2
#define LIMINE_FIRMWARE_TYPE_SBI 3
Размер стека
ID:
#define LIMINE_STACK_SIZE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x224ef0460a8e8926, 0xe1cb0fc25f46ea3d }
Запрос:
struct limine_stack_size_request {
uint64_t id[4];
uint64_t revision;
struct limine_stack_size_response *response;
uint64_t stack_size;
};
stack_size - запрашиваемый размер стека в байтах (также используется для процессоров MP).
Ответ:
struct limine_stack_size_response {
uint64_t revision;
};
HHDM (прямое отображение старшей половины адресного пространства)
ID:
#define LIMINE_HHDM_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x48dcf1cb8ad2b852, 0x63984e959a98244b }
Запрос:
struct limine_hhdm_request {
uint64_t id[4];
uint64_t revision;
struct limine_hhdm_response *response;
};
Ответ:
struct limine_hhdm_response {
uint64_t revision;
uint64_t offset;
};
offset - виртуальное адресное смещение начала прямого отображения старшей половины адресного пространства.
Фреймбуфер
ID:
#define LIMINE_FRAMEBUFFER_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x9d5827dcd881dd75, 0xa3148604f6fab11b }
Запрос:
struct limine_framebuffer_request {
uint64_t id[4];
uint64_t revision;
struct limine_framebuffer_response *response;
};
Ответ:
struct limine_framebuffer_response {
uint64_t revision;
uint64_t framebuffer_count;
struct limine_framebuffer **framebuffers;
};
framebuffer_count - количество доступных фреймбуферов.
framebuffers - указатель на массив из framebuffer_count указателей на структуры struct limine_framebuffer.
ℹ️ ПРИМЕЧАНИЕ
Если фреймбуфер недоступен, ответ не предоставляется.
// Константы для `memory_model`
#define LIMINE_FRAMEBUFFER_RGB 1
struct limine_framebuffer {
void *address;
uint64_t width;
uint64_t height;
uint64_t pitch;
uint16_t bpp; // Бит на пиксель
uint8_t memory_model;
uint8_t red_mask_size;
uint8_t red_mask_shift;
uint8_t green_mask_size;
uint8_t green_mask_shift;
uint8_t blue_mask_size;
uint8_t blue_mask_shift;
uint8_t unused[7];
uint64_t edid_size;
void *edid;
/* Ревизия ответа 1 */
uint64_t mode_count;
struct limine_video_mode **modes;
};
edid указывает на блоб EDID экрана, если он доступен, иначе NULL.
modes - массив из mode_count указателей на struct limine_video_mode, описывающий доступные видео режимы для данного фреймбуфера.
struct limine_video_mode {
uint64_t pitch;
uint64_t width;
uint64_t height;
uint16_t bpp;
uint8_t memory_model;
uint8_t red_mask_size;
uint8_t red_mask_shift;
uint8_t green_mask_size;
uint8_t green_mask_shift;
uint8_t blue_mask_size;
uint8_t blue_mask_shift;
};
Режим страничной адресации
Возможность режима страничной адресации позволяет исполняемому файлу управлять тем, какой режим страничной адресации включён перед передачей управления ему.
ID:
#define LIMINE_PAGING_MODE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x95c1a0edab0944cb, 0xa4e5cb3842f7488a }
Запрос:
struct limine_paging_mode_request {
uint64_t id[4];
uint64_t revision;
struct limine_paging_mode_response *response;
uint64_t mode;
/* Ревизия запроса 1 и выше */
uint64_t max_mode;
uint64_t min_mode;
};
mode - предпочтительный режим страничной адресации ОС; загрузчик всегда должен стремиться выбрать этот режим, если он недоступен или не переопределён пользователем в конфигурационном файле загрузчика.
max_mode - самый высокий режим страничной адресации в числовом порядке, поддерживаемый ОС. Загрузчик откажет в загрузке ОС, если недоступны режимы этого типа или ниже (но равные или выше min_mode).
min_mode - самый низкий режим страничной адресации в числовом порядке, поддерживаемый ОС. Загрузчик откажет в загрузке ОС, если недоступны режимы этого типа или выше (но равные или ниже max_mode).
Если запрос режима страничной адресации не предоставлен, значения mode, max_mode и min_mode, которые предполагает загрузчик, равны LIMINE_PAGING_MODE_<арх>_DEFAULT, LIMINE_PAGING_MODE_<арх>_DEFAULT и LIMINE_PAGING_MODE_<арх>_MIN соответственно.
Если используется ревизия запроса 0, значения max_mode и min_mode, которые предполагает загрузчик, равны значению mode и LIMINE_PAGING_MODE_<арх>_MIN соответственно.
Ответ:
struct limine_paging_mode_response {
uint64_t revision;
uint64_t mode;
};
Ответ указывает, какой режим страничной адресации был фактически включён загрузчиком.
x86-64
Значения, присваиваемые mode, max_mode и min_mode:
#define LIMINE_PAGING_MODE_X86_64_4LVL 0
#define LIMINE_PAGING_MODE_X86_64_5LVL 1
#define LIMINE_PAGING_MODE_X86_64_DEFAULT LIMINE_PAGING_MODE_X86_64_4LVL
#define LIMINE_PAGING_MODE_X86_64_MIN LIMINE_PAGING_MODE_X86_64_4LVL
aarch64
Значения, присваиваемые mode, max_mode и min_mode:
#define LIMINE_PAGING_MODE_AARCH64_4LVL 0
#define LIMINE_PAGING_MODE_AARCH64_5LVL 1
#define LIMINE_PAGING_MODE_AARCH64_DEFAULT LIMINE_PAGING_MODE_AARCH64_4LVL
#define LIMINE_PAGING_MODE_AARCH64_MIN LIMINE_PAGING_MODE_AARCH64_4LVL
riscv64
Значения, присваиваемые mode, max_mode и min_mode:
#define LIMINE_PAGING_MODE_RISCV_SV39 0
#define LIMINE_PAGING_MODE_RISCV_SV48 1
#define LIMINE_PAGING_MODE_RISCV_SV57 2
#define LIMINE_PAGING_MODE_RISCV_DEFAULT LIMINE_PAGING_MODE_RISCV_SV48
#define LIMINE_PAGING_MODE_RISCV_MIN LIMINE_PAGING_MODE_RISCV_SV39
loongarch64
Значения, присваиваемые mode, max_mode и min_mode:
#define LIMINE_PAGING_MODE_LOONGARCH_4LVL 0
#define LIMINE_PAGING_MODE_LOONGARCH_DEFAULT LIMINE_PAGING_MODE_LOONGARCH_4LVL
#define LIMINE_PAGING_MODE_LOONGARCH_MIN LIMINE_PAGING_MODE_LOONGARCH_4LVL
MP (многопроцессорность)
ID:
#define LIMINE_MP_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x95a67b819a1b857e, 0xa0b61b723b6a73e0 }
Запрос:
#define LIMINE_MP_REQUEST_X86_64_X2APIC (1 << 0)
struct limine_mp_request {
uint64_t id[4];
uint64_t revision;
struct limine_mp_response *response;
uint64_t flags;
};
flags - бит 0: включить x2APIC, если возможно. (только x86-64)
ℹ️ ПРИМЕЧАНИЕ
Наличие этого запроса побуждает загрузчик инициализировать вторичные процессоры. Это не будет сделано, если запрос отсутствует.
ℹ️ ПРИМЕЧАНИЕ
Если этот запрос поддерживается, даже в однопроцессорной системе будет предоставлен ответ, содержащий только запись процессора BSP.
x86-64:
Ответ:
#define LIMINE_MP_RESPONSE_X86_64_X2APIC (1 << 0)
struct limine_mp_response {
uint64_t revision;
uint32_t flags;
uint32_t bsp_lapic_id;
uint64_t cpu_count;
struct limine_mp_info **cpus;
};
flags - бит 0: x2APIC включён.
bsp_lapic_id - Local APIC ID процессора BSP.
cpu_count - количество присутствующих CPU. Включает процессор BSP.
cpus - указатель на массив из cpu_count указателей на структуры struct limine_mp_info.
ℹ️ ПРИМЕЧАНИЕ
MTRR вторичных процессоров будут синхронизированы загрузчиком с BSP, как того требует Intel SDM (Vol. 3A, 12.11.5).
struct limine_mp_info;
typedef void (*limine_goto_address)(struct limine_mp_info *);
struct limine_mp_info {
uint32_t processor_id;
uint32_t lapic_id;
uint64_t reserved;
limine_goto_address goto_address;
uint64_t extra_argument;
};
processor_id - ACPI Processor UID, указанный в MADT
lapic_id - Local APIC ID процессора, указанный в MADT
goto_address - атомарная запись в это поле заставляет припаркованный CPU перейти по записанному адресу на стеке размером 64 КиБ (или размером из Возможности размера стека). Указатель на структуру struct limine_mp_info этого CPU передаётся через RDI. В остальном состояние CPU будет таким же, как описано для процессора BSP. Это поле не используется для структуры, описывающей процессор BSP. Для всех CPU это поле гарантированно равно NULL, когда управление впервые передаётся процессору BSP.
extra_argument - поле для свободного использования.
aarch64:
Ответ:
struct limine_mp_response {
uint64_t revision;
uint64_t flags;
uint64_t bsp_mpidr;
uint64_t cpu_count;
struct limine_mp_info **cpus;
};
flags - всегда ноль
bsp_mpidr - MPIDR процессора BSP (как прочитано из MPIDR_EL1, с маскированными Res1).
cpu_count - количество присутствующих CPU. Включает процессор BSP.
cpus - указатель на массив из cpu_count указателей на структуры struct limine_mp_info.
struct limine_mp_info;
typedef void (*limine_goto_address)(struct limine_mp_info *);
struct limine_mp_info {
uint32_t processor_id;
uint32_t reserved1;
uint64_t mpidr;
uint64_t reserved;
limine_goto_address goto_address;
uint64_t extra_argument;
};
processor_id - ACPI Processor UID, указанный в MADT (всегда 0 в системах без ACPI).
mpidr - MPIDR процессора, указанный в MADT или дереве устройств.
goto_address - атомарная запись в это поле заставляет припаркованный CPU перейти по записанному адресу на стеке размером 64 КиБ (или размером из Возможности размера стека). Указатель на структуру struct limine_mp_info этого CPU передаётся через X0. В остальном состояние CPU будет таким же, как описано для процессора BSP. Это поле не используется для структуры, описывающей процессор BSP.
extra_argument - поле для свободного использования.
riscv64
Ответ:
struct limine_mp_response {
uint64_t revision;
uint64_t flags;
uint64_t bsp_hartid;
uint64_t cpu_count;
struct limine_mp_info **cpus;
};
flags - всегда ноль
bsp_hartid - Hart ID процессора BSP, как сообщено протоколом загрузки RISC-V EFI или SBI.
cpu_count - количество присутствующих CPU. Включает процессор BSP.
cpus - указатель на массив из cpu_count указателей на структуры struct limine_mp_info.
struct limine_mp_info;
typedef void (*limine_goto_address)(struct limine_mp_info *);
struct limine_mp_info {
uint64_t processor_id;
uint64_t hartid;
uint64_t reserved;
limine_goto_address goto_address;
uint64_t extra_argument;
};
processor_id - ACPI Processor UID, указанный в MADT (всегда 0 в системах без ACPI).
hartid - Hart ID процессора, указанный в MADT или дереве устройств.
goto_address - атомарная запись в это поле заставляет припаркованный CPU перейти по записанному адресу на стеке размером 64 КиБ (или размером из Возможности размера стека). Указатель на структуру struct limine_mp_info этого CPU передаётся через x10 (a0). В остальном состояние CPU будет таким же, как описано для процессора BSP. Это поле не используется для структуры, описывающей процессор BSP.
extra_argument - поле для свободного использования.
Hart ID BSP для RISC-V
ID:
#define LIMINE_RISCV_BSP_HARTID_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x1369359f025525f9, 0x2ff2a56178391bb6 }
Запрос:
struct limine_riscv_bsp_hartid_request {
uint64_t id[4];
uint64_t revision;
struct limine_riscv_bsp_hartid_response *response;
};
Ответ:
struct limine_riscv_bsp_hartid_response {
uint64_t revision;
uint64_t bsp_hartid;
};
bsp_hartid - Hart ID загрузочного процессора.
ℹ️ ПРИМЕЧАНИЕ
Этот запрос содержит ту же информацию, что и
limine_mp_response.bsp_hartidиз возможности MP, но не запускает другие AP.ℹ️ ПРИМЕЧАНИЕ
На платформах, отличных от RISC-V, ответ не предоставляется.
Карта памяти
ID:
#define LIMINE_MEMMAP_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x67cf3d9d378a806f, 0xe304acdfc50c3c62 }
Запрос:
struct limine_memmap_request {
uint64_t id[4];
uint64_t revision;
struct limine_memmap_response *response;
};
Ответ:
struct limine_memmap_response {
uint64_t revision;
uint64_t entry_count;
struct limine_memmap_entry **entries;
};
entry_count - количество записей карты памяти.
entries - указатель на массив из entry_count указателей на структуры struct limine_memmap_entry.
// Константы для `type`
#define LIMINE_MEMMAP_USABLE 0
#define LIMINE_MEMMAP_RESERVED 1
#define LIMINE_MEMMAP_ACPI_RECLAIMABLE 2
#define LIMINE_MEMMAP_ACPI_NVS 3
#define LIMINE_MEMMAP_BAD_MEMORY 4
#define LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE 5
#define LIMINE_MEMMAP_EXECUTABLE_AND_MODULES 6
#define LIMINE_MEMMAP_FRAMEBUFFER 7
#define LIMINE_MEMMAP_ACPI_TABLES 8
struct limine_memmap_entry {
uint64_t base;
uint64_t length;
uint64_t type;
};
-
LIMINE_MEMMAP_USABLE- регионы адресного пространства, представляющие используемую оперативную память, не содержащую других данных, исполняемого файла, информации загрузчика или чего-либо ценного, и поэтому свободные для использования. -
LIMINE_MEMMAP_RESERVED- регионы адресного пространства, зарезервированные прошивкой, оборудованием или в иных целях и не подлежащие использованию исполняемым файлом. -
LIMINE_MEMMAP_ACPI_RECLAIMABLE- регионы адресного пространства, содержащие данные ACPI, такие как таблицы ACPI и код AML. Исполняемый файл должен убедиться, что данные в этих регионах больше не нужны, прежде чем решить вернуть их для себя. Дополнительную информацию см. в спецификации ACPI. -
LIMINE_MEMMAP_ACPI_NVS- регионы адресного пространства, используемые для хранения неволатильных данных ACPI. Дополнительную информацию см. в спецификации ACPI. -
LIMINE_MEMMAP_BAD_MEMORY- регионы адресного пространства, содержащие ненадёжную оперативную память, которая может быть ненадёжной, и поэтому эти регионы следует рассматривать как зарезервированные. -
LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE- регионы адресного пространства, содержащие оперативную память, используемую для хранения информации загрузчика или прошивки, которая должна быть доступна исполняемому файлу (или, в некоторых случаях, оборудованию, например, для MP-трамплинов). Исполняемый файл должен убедиться, что данные в этих регионах больше не нужны, прежде чем решить вернуть их для себя. -
LIMINE_MEMMAP_EXECUTABLE_AND_MODULES- только для иллюстративных целей и не являются авторитетными источниками для поиска адресов исполняемого файла или модулей. Для этого необходимо использовать специфические возможности Limine (Адрес исполняемого файла и Модули). -
LIMINE_MEMMAP_FRAMEBUFFER- регионы адресного пространства, содержащие фреймбуферы с отображением в памяти. Эти записи существуют только для иллюстративных целей и не должны использоваться для получения адреса любого фреймбуфера. Для этого необходимо использовать Возможность фреймбуфера. -
LIMINE_MEMMAP_ACPI_TABLES(базовая ревизия 4 или выше) - регионы адресного пространства, содержащие таблицы ACPI, как описано в разделе Компоновка памяти при передаче управления, если прошивка не отобразила их уже внутри региона ACPI reclaimable или ACPI NVS.
Для базовых ревизий ≤ 2 память между 0 и 0x1000 никогда не помечается как используемая память.
Для базовой ревизии 4 или выше таблицы ACPI (а именно RSDP, RSDT, XSDT, все таблицы, на которые указывают RSDT и XSDT, FACS, X_FACS, DSDT, X_DSDT - если присутствуют) гарантированно отображены внутри любого из трёх регионов памяти ACPI.
Записи гарантированно отсортированы по базовому адресу от наименьшего к наибольшему.
Записи используемой памяти и памяти, возвращаемой загрузчику, гарантированно выровнены по 4096 байтам как по базе, так и по длине.
Записи используемой памяти и памяти, возвращаемой загрузчику, гарантированно не перекрываются с другими записями. Напротив, все неиспользуемые записи (включая исполняемый файл и модули) не гарантируют выравнивание и могут перекрываться с другими записями.
Тип записи карты памяти EFI → Тип карты памяти Limine
В случае, если прошивка загрузки - EFI, следующее соответствие типов записей карты памяти EFI типам карты памяти Limine гарантированно соблюдается, если не переопределено предыдущими правилами:
-
EfiLoaderCode, EfiLoaderData →
BOOTLOADER_RECLAIMABLE -
EfiBootServicesCode, EfiBootServicesData →
BOOTLOADER_RECLAIMABLE -
EfiACPIReclaimMemory →
ACPI_RECLAIMABLE -
EfiACPIMemoryNVS →
ACPI_NVS -
EfiConventionalMemory →
USABLE -
[всё остальное] →
RESERVED
Точка входа
ID:
#define LIMINE_ENTRY_POINT_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x13d86c035a1cd3e1, 0x2b0caa89d8f3026a }
Запрос:
typedef void (*limine_entry_point)(void);
struct limine_entry_point_request {
uint64_t id[4];
uint64_t revision;
struct limine_entry_point_response *response;
limine_entry_point entry;
};
entry - запрошенная точка входа.
Ответ:
struct limine_entry_point_response {
uint64_t revision;
};
Исполняемый файл
ID:
#define LIMINE_EXECUTABLE_FILE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0xad97e90e83f1ed67, 0x31eb5d1c5ff23b69 }
Запрос:
struct limine_executable_file_request {
uint64_t id[4];
uint64_t revision;
struct limine_executable_file_response *response;
};
Ответ:
struct limine_executable_file_response {
uint64_t revision;
struct limine_file *executable_file;
};
executable_file - указатель на структуру struct limine_file (см. Структура файла) для исполняемого файла. Член string указывает на ту же память, что и значение cmdline, сообщаемое Возможностью командной строки исполняемого файла.
Модули
ID:
#define LIMINE_MODULE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x3e7e279702be32af, 0xca1c4f3bd1280cee }
Запрос:
#define LIMINE_INTERNAL_MODULE_REQUIRED (1 << 0)
#define LIMINE_INTERNAL_MODULE_COMPRESSED (1 << 1)
struct limine_internal_module {
const char *path;
const char *string;
uint64_t flags;
};
struct limine_module_request {
uint64_t id[4];
uint64_t revision;
struct limine_module_response *response;
/* Ревизия запроса 1 */
uint64_t internal_module_count;
struct limine_internal_module **internal_modules;
};
internal_module_count - количество внутренних модулей, переданных исполняемым файлом.
internal_modules - указатель на массив из internal_module_count указателей на структуры struct limine_internal_module.
ℹ️ ПРИМЕЧАНИЕ
Внутренние модули учитываются, если ревизия ответа модуля ≥ 1.
В рамках struct limine_internal_module:
path - путь к загружаемому модулю. Этот путь относителен расположения исполняемого файла.
string - строка, связанная с данным модулем.
flags - флаги, изменяющие поведение загрузки модуля:
-
LIMINE_INTERNAL_MODULE_REQUIRED: завершить работу с ошибкой, если запрошенный модуль не найден. -
LIMINE_INTERNAL_MODULE_COMPRESSED: устарело. Загрузчик может не поддерживать это и аварийно завершить работу вместо этого (начиная с Limine 8.x). Альтернативно: модуль сжат GZ и должен быть распакован загрузчиком. Это учитывается, если ревизия ответа 2 или выше.
Внутренние модули Limine гарантированно загружаются до модулей, указанных пользователем (конфигурационных), и поэтому гарантированно появляются в массиве modules в ответе до модулей, указанных пользователем.
Ответ:
struct limine_module_response {
uint64_t revision;
uint64_t module_count;
struct limine_file **modules;
};
module_count - количество присутствующих модулей.
modules - указатель на массив из module_count указателей на структуры struct limine_file (см. Структура файла).
ℹ️ ПРИМЕЧАНИЕ
Если модули недоступны, ответ не предоставляется.
RSDP
ID:
#define LIMINE_RSDP_REQUEST_ID { LIMINE_COMMON_MAGIC, 0xc5e77b6b397e7b43, 0x27637845accdcf3c }
Запрос:
struct limine_rsdp_request {
uint64_t id[4];
uint64_t revision;
struct limine_rsdp_response *response;
};
Ответ:
struct limine_rsdp_response {
uint64_t revision;
void *address;
};
address - адрес таблицы RSDP. Физический только для базовой ревизии 3.
ℹ️ ПРИМЕЧАНИЕ
Если ACPI недоступен, ответ не предоставляется.
SMBIOS
ID:
#define LIMINE_SMBIOS_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x9e9046f11e095391, 0xaa4a520fefbde5ee }
Запрос:
struct limine_smbios_request {
uint64_t id[4];
uint64_t revision;
struct limine_smbios_response *response;
};
Ответ:
struct limine_smbios_response {
uint64_t revision;
uint64_t entry_32;
uint64_t entry_64;
};
entry_32 - адрес 32-битной точки входа SMBIOS. NULL, если отсутствует. Физический для базовой ревизии ≥ 3.
entry_64 - адрес 64-битной точки входа SMBIOS. NULL, если отсутствует. Физический для базовой ревизии ≥ 3.
ℹ️ ПРИМЕЧАНИЕ
Если SMBIOS недоступен (то есть отсутствуют как 32-битная, так и 64-битная точки входа), ответ не предоставляется.
Таблица системы EFI
ID:
#define LIMINE_EFI_SYSTEM_TABLE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x5ceba5163eaaf6d6, 0x0a6981610cf65fcc }
Запрос:
struct limine_efi_system_table_request {
uint64_t id[4];
uint64_t revision;
struct limine_efi_system_table_response *response;
};
Ответ:
struct limine_efi_system_table_response {
uint64_t revision;
uint64_t address;
};
address - адрес таблицы системы EFI. Физический для базовой ревизии ≥ 3.
ℹ️ ПРИМЕЧАНИЕ
Если EFI недоступен, ответ не предоставляется.
Карта памяти EFI
ID:
#define LIMINE_EFI_MEMMAP_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x7df62a431d6872d5, 0xa4fcdfb3e57306c8 }
Запрос:
struct limine_efi_memmap_request {
uint64_t id[4];
uint64_t revision;
struct limine_efi_memmap_response *response;
};
Ответ:
struct limine_efi_memmap_response {
uint64_t revision;
void *memmap;
uint64_t memmap_size;
uint64_t desc_size;
uint64_t desc_version;
};
memmap - адрес (HHDM, в памяти, возвращаемой загрузчику) карты памяти EFI.
memmap_size - размер карты памяти EFI в байтах.
desc_size - размер дескриптора карты памяти EFI в байтах.
desc_version - версия дескрипторов карты памяти EFI.
ℹ️ ПРИМЕЧАНИЕ
Эта возможность предоставляет данные, подходящие для использования с
RT->SetVirtualAddressMap(), при условии, что изmemmapвычитается смещение HHDM.ℹ️ ПРИМЕЧАНИЕ
Если EFI недоступен, ответ не предоставляется.
Дата при загрузке
ID:
#define LIMINE_DATE_AT_BOOT_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x502746e184c088aa, 0xfbc5ec83e6327893 }
Запрос:
struct limine_date_at_boot_request {
uint64_t id[4];
uint64_t revision;
struct limine_date_at_boot_response *response;
};
Ответ:
struct limine_date_at_boot_response {
uint64_t revision;
int64_t timestamp;
};
timestamp - временная метка UNIX в секундах, взятая из системных часов RTC, представляющая дату и время загрузки.
Адрес исполняемого файла
ID:
#define LIMINE_EXECUTABLE_ADDRESS_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x71ba76863cc55f63, 0xb2644a48c516a487 }
Запрос:
struct limine_executable_address_request {
uint64_t id[4];
uint64_t revision;
struct limine_executable_address_response *response;
};
Ответ:
struct limine_executable_address_response {
uint64_t revision;
uint64_t physical_base;
uint64_t virtual_base;
};
physical_base - физический базовый адрес исполняемого файла.
virtual_base - виртуальный базовый адрес исполняемого файла.
Бинарный блоб дерева устройств (Device Tree Blob)
ID:
#define LIMINE_DTB_REQUEST_ID { LIMINE_COMMON_MAGIC, 0xb40ddb48fb54bac7, 0x545081493f81ffb7 }
Запрос:
struct limine_dtb_request {
uint64_t id[4];
uint64_t revision;
struct limine_dtb_response *response;
};
Ответ:
struct limine_dtb_response {
uint64_t revision;
void *dtb_ptr;
};
dtb_ptr - виртуальный (HHDM) указатель на бинарный блоб дерева устройств в памяти, возвращаемой загрузчику.
ℹ️ ПРИМЕЧАНИЕ
Если DTB недоступен, ответ не предоставляется.
ℹ️ ПРИМЕЧАНИЕ
Информация, содержащаяся в узле
/chosen, может не отражать информацию, переданную тегами загрузчика, и поэтому свойства узла/chosenследует игнорировать.ℹ️ ПРИМЕЧАНИЕ
Если DTB содержал узлы
memory@..., они будут удалены. Исполняемые файлы не должны полагаться на эти узлы и должны использовать вместо этого Возможность карты памяти.
Производительность загрузчика
ID:
#define LIMINE_BOOTLOADER_PERFORMANCE_REQUEST_ID { LIMINE_COMMON_MAGIC, 0x6b50ad9bf36d13ad, 0xdc4c7e88fc759e17 }
Запрос:
struct limine_bootloader_performance_request {
uint64_t id[4];
uint64_t revision;
struct limine_bootloader_performance_response *response;
};
Ответ:
struct limine_bootloader_performance_response {
uint64_t revision;
uint64_t reset_usec;
uint64_t init_usec;
uint64_t exec_usec;
};
reset_usec - время сброса системы в микросекундах относительно произвольной точки в прошлом.
init_usec - время инициализации загрузчика в микросекундах относительно произвольной точки в прошлом.
exec_usec - время передачи управления исполняемому файлу в микросекундах относительно произвольной точки в прошлом.
ℹ️ ПРИМЕЧАНИЕ
Данные, предоставляемые этой возможностью, носят исключительно информационный характер. Таблица данных производительности прошивки ACPI (FPDT) может содержать более точные данные и должна быть предпочтительна, если она существует. Загрузчики могут реализовывать эту возможность с использованием FPDT.
ℹ️ ПРИМЕЧАНИЕ
Загрузчик может считать
reset_usecравным нулю, если он не может или не знает время сброса системы из-за ограничений реализации или платформы.reset_usecобычно будет 0 или значением, близким к нулю, но может быть любым значением относительно любой точки в прошлом.
Структура файла
struct limine_uuid {
uint32_t a;
uint16_t b;
uint16_t c;
uint8_t d[8];
};
#define LIMINE_MEDIA_TYPE_GENERIC 0
#define LIMINE_MEDIA_TYPE_OPTICAL 1
#define LIMINE_MEDIA_TYPE_TFTP 2
struct limine_file {
uint64_t revision;
void *address;
uint64_t size;
char *path;
char *string;
uint32_t media_type;
uint32_t unused;
uint32_t tftp_ip;
uint32_t tftp_port;
uint32_t partition_index;
uint32_t mbr_disk_id;
struct limine_uuid gpt_disk_uuid;
struct limine_uuid gpt_part_uuid;
struct limine_uuid part_uuid;
};
-
revision- ревизия структурыstruct limine_file. -
address- адрес файла. Всегда выровнен как минимум по 4 КиБ. -
size- размер файла. Независимо от размера файла, для всех загруженных модулей гарантируется, что все 4 КиБ блоки памяти, которые они занимают, выделены исключительно им. -
path- путь к файлу в томе с ведущим слэшем. -
string- строка, связанная с файлом. -
media_type- тип носителя, на котором находится файл. -
tftp_ip- если не 0, это IP-адрес TFTP-сервера, с которого был загружен файл. -
tftp_port- аналогично, но порт. -
partition_index- индекс раздела тома, с которого был загружен файл, начинающийся с 1. Если 0, это означает недопустимый или неразделённый диск. -
mbr_disk_id- если не 0, это идентификатор диска, с которого был загружен файл, как указано в его MBR. -
gpt_disk_uuid- если не 0, это UUID диска, с которого был загружен файл, как указано в его GPT. -
gpt_part_uuid- если не 0, это UUID раздела, с которого был загружен файл, как указано в GPT. -
part_uuid- если не 0, это UUID файловой системы раздела, с которого был загружен файл.
Создан: 2025-11-29
Обновлен: 2025-11-29 12:52