1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/input-output-limine

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
PROTOCOL.md 72 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 03.03.2025 16:03 6bc5270

Протокол загрузки Limine

Протокол загрузки Limine представляет собой современный, переносимый, функциональный и расширяемый протокол загрузки.

Этот файл служит официальным централизованным сборником функций, составляющих протокол загрузки Limine. Другие загрузчики могут поддерживать дополнительные неофициальные функции, но настоятельно рекомендуется избегать фрагментации и отправлять новые функции через запрос на включение в репозиторий Limine.

Файл limine.h предоставляет реализацию всех структур и констант, описанных в этом документе, для языков C и C++.

Общие замечания

Все указатели имеют ширину Yöntem 64 бита. Все указатели указывают на объект с уже добавленным к нему смещением высшего полумапа, за исключением случаев, когда это указано иначе.

Конвенция вызова соответствует C ABI для конкретной архитектуры (SysV для x86, AAPCS для aarch64).

Основные версии протокола

Протокол загрузки Limine представлен несколькими основными версиями; до настоящего времени определены только две основные версии: 0 и 1.

Основные версии протокола изменяют определенные поведения протокола загрузки Limine вне любой конкретной функции. Подробности будут описаны по мере необходимости в этом спецификации.

Основная версия 0 считается устаревшей, и она является по умолчанию основной версией, которую предполагается, что ядро запрашивает и следует при отсутствии метки основной версии от ядра для обратной совместимости.

Метка основной версии — это набор из трех значений 64 бита, расположенных где-то в двоичном файле ядра на границе выравненного на 8 байтов; первые два значения представляют собой магическое число для загрузчика, чтобы он мог идентифицировать метку, а последнее значение — запрошенная основная версия. Отсутствие метки основной версии означает версию 0.

#define LIMINE_BASE_REVISION(N) \
    uint64_t limine_base_revision[3] = { 0xf9562b2d5c95a6c8, 0x6a7b384944536bdc, (N) };

Если загрузчик прекращает поддержку более старой основной версии, загрузчик должен отказаться от загрузки ядра, запрашивающего такую основную версию. Если загрузчик еще не поддерживает запрошенную основную версию (например, если запрошенная основная версия выше максимальной основной версии, поддерживаемой загрузчиком), он должен загрузить ядро используя любую произвольную версию, которую он поддерживает, и сообщить ядру о невозможности выполнения требований путем оставления третьего компонента метки основной версии без изменения. С другой стороны, если запрошенная основная версия ядра поддерживается, третий компонент метки основной версии должен быть установлен загрузчиком в 0.

Замечание: это означает, что в отличие от случая, когда загрузчик прекращает поддержку более старой основной версии и сам отвечает за отказ от загрузки ядра, в случае, когда загрузчик еще не поддерживает запрошенную основную версию ядра, ответственность за отказ ложится на само ядро (или оно должно как-то обрабатывать данное условие).

Функции

Протокол основан на концепции запрос/ответ — совокупно названных "функциями", — где ядро запрашивает некоторое действие или информацию у загрузчика, а загрузчик отвечает соответственно, если способен сделать это.

На языке C, функция состоит из двух структур: запроса и ответа.

Запрос имеет три обязательных поля в начале структуры:

struct limine_example_request {
    uint64_t id[4];
    uint64_t revision;
    struct limine_example_response *response;
    ... дополнительные поля следуют ...
};
  • id - Идентификатор запроса. Это выравненное на 8 байтов магическое число, которое загрузчик будет просматривать внутри исполняемого файла для поиска запросов. Запросы могут находиться в любом месте внутри исполняемого файла, если они выравнены на 8 байтов. Может быть только один запрос с тем же идентификатором. Загрузчик откажется загружать исполняемый файл с несколькими запросами одного и того же идентификатора. В качестве альтернативы можно явно предоставить список запросов через раздел исполняемого файла. Смотрите "Раздел Limine Requests".
  • revision - Версия запроса, предоставленная ядром. Она начинается с 0 и увеличивается каждый раз, когда добавляются новые поля или функциональность к структуре запроса. Загрузчики обрабатывают запросы в обратно совместимом режиме, всегда. Это означает, что если загрузчик не поддерживает версию запроса, он обработает запрос, как будто бы это была самая высокая версия, которую поддерживает загрузчик.
  • response - Это поле заполняется загрузчиком во время загрузки указателем на структуру ответа, если запрос был успешно обработан. Если запрос недоступен или не был успешно обработан, это поле остается нетронутым, то есть если оно было установлено в NULL, оно останется таким.

Ответ имеет только одно обязательное поле в начале структуры:

struct limine_example_response {
    uint64_t revision;
    ... дополнительные поля следуют ...
};
  • revision - Как и для запросов, загрузчики помечают ответы номером версии. Этот номер версии не связан между запросами и ответами, поскольку они увеличиваются отдельно при добавлении новых полей или изменения функциональности. Загрузчики установят номер версии на тот, который они предоставляют, и этот номер всегда обратно совместим, то есть все, что поддерживают более высокие версии, поддерживают также более низкие версии.

Это всё, что относится к функциям. Для списка официальных функций Limine прочитайте раздел "Список функций" ниже.

Раздел Limine Requests

Замечание: эта поведение устарела начиная с основной версии протокола 1Для ядер, запрашивающих устаревшую основную версию 0, если исполняемый файл ядра содержит раздел .limine_reqs, загрузчик вместо сканирования исполняемого файла за запросами, получит запросы из NULL-терминированного массива указателей на предоставленные запросы, содержащихся в данном разделе.

Расположение памяти при передаче управления

Протокол обязывает ядра загружаться на адресах или выше 0xffffffff80000000. Ядра нижней половины не поддерживаются.

При передаче управления ядро будет правильно загружено и отображено с соответствующими правами MMU, как контроллер, на запрошенном виртуальном адресе памяти (предоставленном, если он находится на или выше 0xffffffff80000000).

Нет гарантий относительно конкретного местоположения физической памяти, кроме того, что ядро гарантированно будет физически непрерывным. Чтобы определить, где загружено ядро в физической памяти, см. функцию Адрес Ядра ниже.

Вместе с загруженным ядром, загрузчик установит карты памяти следующим образом:

Базовый физический адрес |                               | Базовый виртуальный адрес
-------------------------|-------------------------------|---------------------------
                          |    (4 ГБ - 0x1000) и любые   |
  0x0000000000001000     |  дополнительные области карты |  0x0000000000001000
                          |    (только для базовой версии 0)
-------------------------|-------------------------------|---------------------------
                          |     4 ГБ и дополнительные     |
  0x0000000000000000     |  области карты памяти в зависимости |      Начало HHDM
                          |       от базовой версии       |

Где "Начало HHDM" возвращается функцией Высшего Полумапа (см. ниже). Эти карты являются контроллером, чтение, запись, выполнение (-rwx).

Для базовой версии 0, выше-4ГБ идентификационные и HHDM карты памяти покрывают любую область карты памяти.

Для базовой версии 1, выше-4ГБ HHDM карты памяти не включают области карты памяти типов:

  • зарезервированные
  • плохая память

Страницевые таблицы загрузчика находятся в памяти, доступной для освобождения загрузчиком (см. Функцию Карта памяти ниже), и их конкретная структура неопределена, пока они обеспечивают вышеуказанные карты памяти.

Если ядро является независимым по положению исполняемым файлом, загрузчик свободен переопределить его, как ему угодно, потенциально выполняя случайное перемещение ядра (как указано в конфигурации).

Кэширование

x86-64

Исполняемый файл ядра, загруженный на адресе или выше 0xffffffff80000000, видит все свои сегменты отображёнными с использованием кэширования с обратной связью (WB) на уровне страницевых таблиц.

Все HHDM и идентификационные области памяти отображаются с использованием кэширования с обратной связью (WB) на уровне страницевых таблиц, за исключением областей экрана, которые отображаются с использованием кэширования соединения (WC) на уровне страницевых таблиц.

Устройство PAT (Page Attribute Table) определено следующим образом:

PAT0 -> WB
PAT1 -> WT
PAT2 -> UC-
PAT3 -> UC
PAT4 -> WP
PAT5 -> WC
PAT6 -> неопределено
PAT7 -> неопределено

MTRRs оставлены такими, какие они были установлены прошивкой.

aarch64

Исполняемый файл ядра, загруженный на адресе или выше 0xffffffff80000000, видит все свои сегменты отображёнными с использованием нормального кэширования с обратной связью RW-Аллоцирование не-транзитное.

Все HHDM и идентификационные области памени отображаются с использованием нормального кэширования с обратной связью RW-Аллоцирование не-транзитное, за исключением областей экрана, которые отображаются с использованием неопределенного кэширования, корректного для использования с экраном платформы.

Зарегистратор MAIR_EL1 будет содержать записи для вышеупомянутых режимов кэширования, в неопределенном порядке.

Чтобы получить доступ к областям MMIO, ядро должно обеспечить использование правильного режима кэширования самостоятельно.

riscv64

Если доступна расширение Svpbmt, все области памяти экрана отображаются с PBMT=NC для активации оптимизации соединения. Исполняемый файл ядра, загруженный на адресе или выше 0xffffffff80000000, и все HHDM и идентификационные области памени отображаются с использованием стандартного PBMT=PMA.

Если расширение Svpbmt недоступно, никакие PMAs не могут быть переопределены (по сути, всё отображается с PBMT=PMA).

Машина состояния при входе

x86-64

rip будет точкой входа, определенной как часть формата исполняемого файла, за исключением случаев, когда запрошена функция точки входа (см. ниже), тогда значение rip будет взято оттуда.

При входе все регистры сегментов загружены как 64-битные сегменты кода/данных, пределы и базы игнорируются, так как это 64-битный режим.

Регистр GDT загружен для указания на GDT, в памяти, доступной для освобождения загрузчиком, с минимум следующими вхождениями, начиная с смещения 0:

  • Описание null-_DESCRIPTOR
  • 16-битный кодовый DESCRIPTOR. База = 0, ограничение = 0xFFFF. Читаемый.
  • 16-битный данных DESCRIPTOR. База = 0, ограничение = 0xFFFF. Записываемый.
  • 32-битный кодовый DESCRIPTOR. База = 0, ограничение = 0xFFFFFFFF. Читаемый.
  • 32-битный данные DESCRIPTOR. База = 0, ограничение = 0xFFFFFFFF. Записываемый.
  • 64-битный кодовый DESCRIPTOR. База и ограничение не имеют значения. Читаемый.
  • 64-битный данные DESCRIPTOR. База и ограничение не имеют значения. Записываемый.

Таблица прерываний (IDT) находится в неопределенном состоянии. Ядро должно загрузить свою собственную таблицу.

Флаг IF, флаг VM и направление флаги сброшены при входе. Другие флаги неопределены.Управление страницами (PG) активировано (cr0), выполнение программ (PE) активировано (cr0), расширенное управление страницами (PAE) активировано (cr4), защита памяти от записи (WP) активировано (cr0), режим совместной работы между 32- и 64-битными системами (LME) активировано (EFER), защита от выполнения непрерывных блоков данных (NX) активировано (EFER) если доступно. Если запрошено использование 5-уровневого управления страницами и это возможно, то 5-уровневое управление страницами активируется (бит LA57 в cr4).

Дверь A20 открыта.

Старые PIC (если доступны) и IRQs IO APIC (только те, у которых режим доставки фиксирован (0b000) или наименьший приоритет (0b001)) все скрыты.

Если загружено через EFI/UEFI, службы загрузки завершаются.

rsp устанавливается так, чтобы указывать на стек, находящийся в памяти, которую можно использовать повторно после загрузки, размер которого составляет как минимум 64 КБ (65536 байт) или размер, указанный в запросе на размер стека (см. ниже). Недействительный адрес возврата 0 помещается на стек перед переходом в ядро.

Все остальные общие регистры назначаются значению 0.

aarch64

PC будет точкой входа, определённой как часть формата исполняемого файла, за исключением случая, когда запрошенная функция точки входа (см. ниже), тогда значение PC будет взято оттуда.

Содержимое регистра VBAR_EL1 неопределено, и ядро должно загрузить своё собственное содержимое.

Содержимое регистра MAIR_EL1 описано выше, в разделе о кэшировании.

Все прерывания скрыты (PSTATE.{D, A, I, F} установлены в 1).

Ядро запускается в режиме AArch64 EL1t (EL1 с PSTATE.SP установленным в 0, PSTATE.E установленным в 0, и PSTATE.nRW установленным в 0).

Другие поля PSTATE неопределены.

При входе: MMU (SCTLR_EL1.M) активирован, кэши инструкций и данных (SCTLR_EL1.{I, C}) активированы, проверка выравнивания данных (SCTLR_EL1.A) отключена. Проверка выравнивания стека (SCTLR_EL1.{SA, SA0}) активирована. Другие поля SCTLR_EL1 сброшены до 0 или до их зарезервированного значения.

Высшие уровни EL не мешают доступу к векторным или командам с плавающей запятой.

Высшие уровни EL не мешают доступу к общим таймерам и счетчикам.

Размер используемых гранул преобразования неопределён.

Если загружено через EFI/UEFI, службы загрузки завершаются.

SP устанавливается таким образом, чтобы указывать на стек, находящийся в памяти, которую можно использовать повторно после загрузки, размер которого составляет как минимум 64 КБ (65536 байт) или размер, указанный в запросе на размер стека (см. ниже).

Все остальные общие регистры (включая X29 и X30) устанавливаются в 0. Векторные регистры находятся в неопределённом состоянии.

riscv64

При входе машина выполняется в режиме Supervisor.

pc будет точкой входа, определённой как часть формата исполняемого файла, за исключением случая, когда запрошенная функция точки входа (см. ниже), тогда значение pc будет взято оттуда.

x1(ra) устанавливается в 0, ядро не должно возвращаться из точки входа.

x2(sp) устанавливается таким образом, чтобы указывать на стек, находящийся в памяти, которую можно использовать повторно после загрузки, размер которого составляет как минимум 64 КБ (65536 байт) или размер, указанный в запросе на размер стека (см. ниже).

x3(gp) устанавливается в 0, ядро должно загрузить свой собственный глобальный указатель, если требуется.

Все остальные общие регистры, кроме x5(t0), устанавливаются в 0.

Если загружено через EFI/UEFI, службы загрузки завершаются.

stvec находится в неопределённом состоянии. sstatus.SIE и sie устанавливаются в 0.

sstatus.FS и sstatus.XS оба устанавливаются в Off.

Управление страницами активировано с режимом управления страницами, указанным в запросе на режим управления страницами (см. ниже).

(A)PLIC, если он существует, находится в неопределённом состоянии.

Список функций

Идентификаторы запросов состоят из четырёх 64-битных беззнаковых целых чисел, но первые два являются общими для каждого запроса:

#define LIMINE_COMMON_MAGIC 0xc7b1dd30df4c8b88, 0x0a82e883a194f07b

Информация о загрузочном модуле

ID:

#define LIMINE_BOOTLOADER_INFO_REQUEST { 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_STACK_SIZE_REQUEST { 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 — запрашиваемый размер стека в байтах (также используется для процессоров SMP).

Ответ:

struct limine_stack_size_response {
    uint64_t revision;
};

HHDM (Direct Higher Half Mapping) Feature

ID:

#define LIMINE_HHDM_REQUEST { 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 — виртуальное адресное смещение начала карты высшей половины.

Устаревшая функция терминал

Примечание: Эта функция устарела и была удалена начиная с версии Limine 5.x, пожалуйста, не используйте её.

ID:

#define LIMINE_TERMINAL_REQUEST { LIMINE_COMMON_MAGIC, 0xc8ac59310c2b0844, 0xa68d0c7265d38878 }

Запрос:

typedef void (*limine_terminal_callback)(struct limine_terminal *, uint64_t, uint64_t, uint64_t, uint64_t);

struct limine_terminal_request {
    uint64_t id[4];
    uint64_t revision;
    struct limine_terminal_response *response;
    limine_terminal_callback callback;
};
  • callback — указатель на обратный вызов функции.

Ответ:

typedef void (*limine_terminal_write)(struct limine_terminal *terminal, const char *string, uint64_t length);

struct limine_terminal_response {
    uint64_t revision;
    uint64_t terminal_count;
    struct limine_terminal **terminals;
    limine_terminal_write write;
};
```* `terminal_count`  количество терминалов.
* `terminals`  указатель на массив из `terminal_count` указателей на структуры `struct limine_terminal`.
* `write`  физический указатель на функцию записи терминала.
Функция не является потоко-безопасной и не рекурсивной на уровне терминала.
Это означает, что несколько терминалов могут быть вызваны одновременно, а также несколько обратных вызовов могут быть обработаны одновременно.
Параметр `terminal` указывает на структуру `struct limine_terminal`, которая должна использоваться для вывода строки; параметр `string` указывает на строку для печати; параметр `length` содержит длину строки для печати в байтах.

```c
struct limine_terminal {
    uint64_t columns;
    uint64_t rows;
    struct limine_framebuffer *framebuffer;
};
  • columns и rows — колонки и строки, предоставляемые терминалом.
  • framebuffer — буфер экрана, связанный с данным терминалом.

Примечание: Пропуск этого запроса приведёт к тому, что загрузочный модуль не инициализирует службу терминалов.

Обратный вызов терминала

Обратный вызов — это функция, являющаяся частью ядра, которая вызывается терминалом во время выполнения write() при встрече события или последовательности экранирования, которое терминал не может обработать самостоятельно, и ядро хочет получить уведомление для самостоятельной обработки.

Возврат из обратного вызова продолжает вызов write(), который затем возвращает своё вызывающее нормально.

Не возвращаясь из обратного вызова, можно оставить терминал в неопределённом состоянии и вызвать проблемы.

Функция обратного вызова имеет следующий прототип:

void callback(struct limine_terminal *terminal, uint64_t type, uint64_t, uint64_t, uint64_t);

Аргумент terminal — это указатель на структуру терминала Limine, представляющую терминал, вызвавший обратный вызов.

Цель последних трёх аргументов зависит от аргумента type.

Типы обратных вызовов следующие:

  • LIMINE_TERMINAL_CB_DEC — (значение типа: 10)

Этот обратный вызов активируется при встрече последовательности DEC Private Mode (DECSET/DECRST), которую терминал не может обработать самостоятельно. Аргументы этого обратного вызова: terminal, type, values_count, values, final.

values_count — это количество значений в массиве, указанном указателем values. values — указатель на массив значений типа uint32_t, которые передаются в DEC private escape. final — это конечный символ в последовательности DEC private escape (обычно l или h).

  • LIMINE_TERMINAL_CB_BELL — (значение типа: 20)

Этот обратный вызов активируется при необходимости звукового сигнала (например, при встрече символа звукового сигнала \a). Аргументы этого обратного вызова: terminal, type, unused1, unused2, unused3.

  • LIMINE_TERMINAL_CB_PRIVATE_ID — (значение типа: 30)

Этот обратный вызов активируется при необходимости ответа ядра на запрос DEC private identification. Аргументы этого обратного вызова: terminal, type, unused1, unused2, unused3.

  • LIMINE_TERMINAL_CB_STATUS_REPORT — (значение типа 40)

Этот обратный вызов активируется при необходимости ответа ядра на запрос ECMA-48 status report. Аргументы этого обратного вызова: terminal, type, unused1, unused2, unused3.

  • LIMINE_TERMINAL_CB_POS_REPORT — (значение типа 50)

Этот обратный вызов активируется при необходимости ответа ядра на запрос ECMA-48 cursor position report. Аргументы этого обратного вызова: terminal, type, x, y, unused3. Где x и y представляют положение курсора в момент активации обратного вызова.

  • LIMINE_TERMINAL_CB_KBD_LEDS — (значение типа 60)

Этот обратный вызов срабатывает всякий раз, когда ядро должно отвечать на запрос изменения состояния светодиодной клавиатуры. Аргументами этого обратного вызова являются: terminal, type, led_state, unused2, unused3. Значение led_state может иметь одно из следующих значений: 0, 1, 2, или 3. Эти значения означают: выключить все светодиоды, включить скролл-лок, включить нум-лок и включить капсл-лок соответственно.

  • LIMINE_TERMINAL_CB_MODE — (тип значения: 70)

Этот обратный вызов срабатывает всякий раз, когда встречается последовательность переключения режима ECMA-48, которую терминал не может обработать самостоятельно. Аргументами этого обратного вызова являются: terminal, type, values_count, values, final.

values_count — это количество значений в массиве, указываемом аргументом values. values — это указатель на массив значений типа uint32_t, переданных в последовательность переключения режима. final — это заключительный символ последовательности переключения режима (обычно l или h).

  • LIMINE_TERMINAL_CB_LINUX — (тип значения 80)

Этот обратный вызов срабатывает всякий раз, когда встречается частная последовательность экранирования Linux, которую терминал не может обработать самостоятельно. Аргументами этого обратного вызова являются: terminal, type, values_count, values, unused3.

values_count — это количество значений в массиве, указываемом аргументом values. values — это указатель на массив значений типа uint32_t, переданных в частную последовательность экранирования Linux.

Управление контекстом терминала

Функция write() также может использоваться для установки и восстановления контекста терминала, а также полной перезагрузки терминала.

Для достижения этой цели используются специальные значения для аргумента length. Эти значения представлены ниже:

/* Ответ версии 0 */
#define LIMINE_TERMINAL_CTX_SIZE ((uint64_t)(-1))
#define LIMINE_TERMINAL_CTX_SAVE ((uint64_t)(-2))
#define LIMINE_TERMINAL_CTX_RESTORE ((uint64_t)(-3))
#define LIMINE_TERMINAL_FULL_REFRESH ((uint64_t)(-4))
/* Ответ версии 1 */
#define LIMINE_TERMINAL_OOB_OUTPUT_GET ((uint64_t)(-10))
#define LIMINE_TERMINAL_OOB_OUTPUT_SET ((uint64_t)(-11))

Для CTX_SIZE переменная ptr должна указывать на место, куда терминал будет записывать одиночное значение uint64_t, содержащее размер контекста терминала.

Для CTX_SAVE и CTX_RESTORE переменная ptr должна указывать на место, куда терминал будет сохранять или восстанавливать свой контекст соответственно. Это место должно иметь размер, совпадающий со значением, полученным из CTX_SIZE.Для FULL_REFRESH переменная ptr не используется. Этот метод следует использовать после того, как контроль за буфером экрана был взят на себя, и терминал загрузчика должен полностью перерисовать буфер экрана, чтобы избежать несоответствий.

Если номер ответа равен или превышает 1, то OOB_OUTPUT_GET и OOB_OUTPUT_SET позволяют получить и установить настройки вывода вне основного потока терминала. ptr указывает на место, куда терминал будет записывать или читать одиночное значение uint64_t, содержащее биты, представляющие эти настройки. Возможные настройки представлены ниже:

#define LIMINE_TERMINAL_OOB_OUTPUT_OCRNL (1 << 0)
#define LIMINE_TERMINAL_OOB_OUTPUT_OFDEL (1 << 1)
#define LIMINE_TERMINAL_OOB_OUTPUT_OFILL (1 << 2)
#define LIMINE_TERMINAL_OOB_OUTPUT_OLCUC (1 << 3)
#define LIMINE_TERMINAL_OOB_OUTPUT_ONLCR (1 << 4)
#define LIMINE_TERMINAL_OOB_OUTPUT_ONLRET (1 << 5)
#define LIMINE_TERMINAL_OOB_OUTPUT_ONOCR (1 << 6)
#define LIMINE_TERMINAL_OOB_OUTPUT_OPOST (1 << 7)

Эффект каждого из этих вариантов соответствует эффекту опций stty(1) с тем же названием.

x86-64

Кроме того, ядро должно гарантировать при вызове write(), что:

  • Либо GDT, предоставленная загрузчиком, всё ещё правильно загружена, либо загружена пользовательская GDT с минимальными следующими дескрипторами в указанном порядке:

    • Нулевой дескриптор
    • Дескриптор кода 16-битного. Основание = 0, ограничение = 0xffff. Читаемый.
    • Дескриптор данных 16-битного. Основание = 0, ограничение = 0xffff. Записываемый.
    • Дескриптор кода 32-битного. Основание = 0, ограничение = 0xffffffff. Читаемый.
    • Дескриптор данных 32-битного. Основание = 0, ограничение = 0xffffffff. Записываемый.
    • Дескриптор кода 64-битного. Основание и ограничение не имеют значения. Читаемый.
    • Дескриптор данных 64-битного. Основание и ограничение не имеют значения. Записываемый.
  • Виртуальное адресное пространство, которое сейчас загружено, всё ещё является тем, которое было предоставлено загрузчиком при входе, или загружено пользовательское виртуальное адресное пространство, которое идентично отображает область памяти буфера экрана, связанного с терминалом, и всех областей памяти, которые могут быть заняты загрузчиком, с правами чтения, записи и выполнения.

  • Процедура вызывается по её физическому адресу (значение указателя функции уже является физическим), которое должно быть идентично отображено.

  • Области памяти, которые могут быть заняты загрузчиком, остаются нетронутыми до тех пор, пока ядро не завершит использование предоставляемых загрузчиком средств (этот терминал является одним из таких средств).

Примечания относительно сегментных регистров и FPU:

Значения сегментов FS и GS гарантируются сохранены через вызов. Все остальные сегментные регистры могут иметь свою "скрытую" часть перезаписанной, но Limine гарантирует, что "видимая" часть будет восстановлена до значения, используемого во время вызова, прежде чем вернуться.

Ни один другой регистр, кроме сегментных и общего назначения, не будет использован. Особенно, это означает, что нет необходимости сохранять и восстанавливать состояние FPU, SSE или AVX при вызове функции записи терминала.

aarch64

Кроме того, ядро должно гарантировать при вызове write(), что:

  • Виртуальное адресное пространство, которое сейчас загружено, всё ещё является тем, которое было предоставлено загрузчиком при входе, или загружено пользовательское виртуальное адресное пространство, которое идентично отображает область памяти буфера экрана, связанного с терминалом, и всех областей памяти, которые могут быть заняты загрузчиком, с правами чтения, записи и выполнения.

  • Процедура вызывается по её физическому адресу (значение указателя функции уже является физическим), которое должно быть идентично отображено.

  • Области памяти, которые могут быть заняты загрузчиком, остаются нетронутыми до тех пор, пока ядро не завершит использование предоставляемых загрузчиком средств (этот терминал является одним из таких средств).

Примечания относительно использования регистров:

Ни один другой регистр, кроме общего назначения, не будет использован. Особенно, это означает, что нет необходимости сохранять и восстанавливать состояние SIMD при вызове функции записи терминала.

Характеристики терминала

Терминал должен стремиться обеспечивать совместимость с консолью Linux.

Возможность управления буфером экрана

ID:

#define LIMINE_FRAMEBUFFER_REQUEST { 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;
};

modes представляет собой массив из mode_count указателей на структуры 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 { LIMINE_COMMON_MAGIC, 0x95c1a0edab0944cb, 0xa4e5cb3842f7488a }
``````c
struct limine_paging_mode_request {
    uint64_t id[4];
    uint64_t revision;
    struct limine_paging_mode_response *response;
    uint64_t mode;
    uint64_t flags;
};

Оба поля mode и flags являются архитектурно зависимыми.

Макрос LIMINE_PAGING_MODE_DEFAULT предоставляется всеми архитектурами для выбора дефолтного режима страницирования (см. ниже).

Ответ:

struct limine_paging_mode_response {
    uint64_t revision;
    uint64_t mode;
    uint64_t flags;
};

Ответ показывает, какой режим страницирования был действительно активирован загрузчиком. Ядра должны быть готовы работать с ситуацией, когда запрошенный режим страницирования не поддерживается аппаратной частью.

x86-64

Значения для mode:

#define LIMINE_PAGING_MODE_X86_64_4LVL 0
#define LIMINE_PAGING_MODE_X86_64_5LVL 1

#define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_X86_64_4LVL

На данный момент никакие флаги не определены.

По умолчанию используется режим LIMINE_PAGING_MODE_X86_64_4LVL (когда этот запрос не предоставлен).

aarch64

Значения для mode:

#define LIMINE_PAGING_MODE_AARCH64_4LVL 0
#define LIMINE_PAGING_MODE_AARCH64_5LVL 1

#define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_AARCH64_4LVL

На данный момент никакие флаги не определены.

По умолчанию используется режим LIMINE_PAGING_MODE_AARCH64_4LVL (когда этот запрос не предоставлен).

riscv64

Значения для 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_DEFAULT LIMINE_PAGING_MODE_RISCV_SV48

На данный момент никакие флаги не определены.

По умолчанию используется режим LIMINE_PAGING_MODE_RISCV_SV48 (когда этот запрос не предоставлен).

Возможность управления 5-уровневым режимом страницирования

Примечание: Эта функция была отменена в пользу функции управления страницами (Paging Mode feature) и удалена начиная с версии Limine 5.x.

ID:

#define LIMINE_5_LEVEL_PAGING_REQUEST { LIMINE_COMMON_MAGIC, 0x94469551da9b3192, 0xebe5e86db7382888 }

Запрос:

struct limine_5_level_paging_request {
    uint64_t id[4];
    uint64_t revision;
    struct limine_5_level_paging_response *response;
};

Ответ:

struct limine_5_level_paging_response {
    uint64_t revision;
};

Примечание: Присутствие этого запроса заставляет загрузочный модуль активировать режим работы x86-64 5-уровневого управления страницами. Если запрос отсутствует, режим не будет активирован. Если указатель ответа изменён на действительный указатель, режим 5-уровневого управления страницами будет активирован.

Функция SMP (многопроцессорной системы)

ID:

#define LIMINE_SMP_REQUEST { LIMINE_COMMON_MAGIC, 0x95a67b819a1b857e, 0xa0b61b723b6a73e0 }

Запрос:

struct limine_smp_request {
    uint64_t id[4];
    uint64_t revision;
    struct limine_smp_response *response;
    uint64_t flags;
};
  • flags - Бит 0: Включает X2APIC, если возможно. (только для x86-64)

x86-64:

Ответ:

struct limine_smp_response {
    uint64_t revision;
    uint32_t flags;
    uint32_t bsp_lapic_id;
    uint64_t cpu_count;
    struct limine_smp_info **cpus;
};
  • flags - Бит 0: X2APIC был включен.
  • bsp_lapic_id - Локальный APIC ID процессора-инициатора.
  • cpu_count - Количество присутствующих ЦПУ. Включает процессор-инициатор.
  • cpus - Указатель на массив из cpu_count указателей на структуры struct limine_smp_info.

Примечание: Присутствие этого запроса заставляет загрузочный модуль инициализировать вторичные процессоры. Это не будет выполнено, если запрос отсутствует.

Примечание: MTRRs вторичных процессоров будут синхронизированы загрузочным модулем с основным процессором, как требует Intel SDM (Vol. 3A, 12.11.5).

struct limine_smp_info;

typedef void (*limine_goto_address)(struct limine_smp_info *);

struct limine_smp_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 - Локальный APIC ID процессора, как указано в MADT
  • goto_address - Атомарное изменение этого поля вызывает паркованный ЦПУ перейти к указанному адресу, используя стэк размером 64КБ (или размер стэка, запрошенного). Указатель на структуру struct limine_smp_info передается в регистре RDI. Кроме того, состояние ЦПУ будет таким же, как описано для процессора-инициатора. Это поле не используется для структуры, описывающей процессор-инициатор. Для всех ЦПУ это поле гарантированно равно NULL при первом переходе управления к процессору-инициатору.
  • extra_argument - Поле для свободного использования.

aarch64:

Ответ:

struct limine_smp_response {
    uint64_t revision;
    uint64_t flags;
    uint64_t bsp_mpidr;
    uint64_t cpu_count;
    struct limine_smp_info **cpus;
};
  • flags - Всегда равен нулю
  • bsp_mpidr - MPIDR процессора-инициатора (как прочитано из MPIDR_EL1, с Res1 маскированным).
  • cpu_count - Количество присутствующих ЦПУ. Включает процессор-инициатор.
  • cpus - Указатель на массив из cpu_count указателей на структуры struct limine_smp_info.

Примечание: Присутствие этого запроса заставляет загрузочный модуль инициализировать вторичные процессоры. Это не будет выполнено, если запрос отсутствует.

struct limine_smp_info;

typedef void (*limine_goto_address)(struct limine_smp_info *);

struct limine_smp_info {
    uint32_t processor_id;
    uint32_t gic_iface_no;
    uint64_t mpidr;
    uint64_t reserved;
    limine_goto_address goto_address;
    uint64_t extra_argument;
};
  • processor_id - ACPI Processor UID, как указано в MADT
  • gic_iface_no - Номер интерфейса GIC процессора, как указано в MADT (возможно всегда 0)
  • mpidr - MPIDR процессора, как указано в MADT или дереве устройств
  • goto_address - Атомарное изменение этого поля вызывает паркованный ЦПУ перейти к указанному адресу, используя стэк размером 64КБ (или размер стэка, запрошенного). Указатель на структуру struct limine_smp_info передается в регистре X0. Кроме того, состояние ЦПУ будет таким же, как описано для процессора-инициатора. Это поле не используется для структуры, описывающей процессор-инициатор.
  • extra_argument - Поле для свободного использования.

riscv64

Ответ:

struct limine_smp_response {
    uint64_t revision;
    uint64_t flags;
    uint64_t bsp_hartid;
    uint64_t cpu_count;
    struct limine_smp_info **cpus;
};
  • flags - Всегда равен нулю
  • bsp_hartid - Hart ID процессора-инициатора, как отчет UEFI RISC-V Boot Protocol или SBI.
  • cpu_count - Количество присутствующих ЦПУ. Включает процессор-инициатор.
  • cpus - Указатель на массив из cpu_count указателей на структуры struct limine_smp_info.

Примечание: Присутствие этого запроса заставляет загрузочный модуль инициализировать вторичные процессоры. Это не будет выполнено, если запрос отсутствует.

struct limine_smp_info;
``````c
typedef void (*limine_goto_address)(struct limine_smp_info *);

struct limine_smp_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 - Атомарное изменение этого поля вызывает паркованный ЦПУ перейти к указанному адресу, используя стэк размером 64КБ (или размер стэка, запрошенного). Указатель на структуру struct limine_smp_info передается в регистре x10 (a0). Кроме того, состояние ЦПУ будет таким же, как описано для процессора-инициатора. Это поле не используется для структуры, описывающей процессор-инициатор.
  • extra_argument - Поле для свободного использования.

Функция карты памяти

ID:

#define LIMINE_MEMMAP_REQUEST { 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_KERNEL_AND_MODULES     6
#define LIMINE_MEMMAP_FRAMEBUFFER            7

struct limine_memmap_entry {
    uint64_t base;
    uint64_t length;
    uint64_t type;
};

Примечание: Память между 0 и 0x1000 никогда не помечается как доступная для использования. Ядра и модули, загруженные в память, также не помечаются как доступные для использования. Они помечаются как "Kernel/Modules". Записи гарантированно сортированы по базовому адресу, от самого маленького до самого большого. Доступные и доступные для использования записи гарантированно выравнены по 4096 байтам для обоих базового адреса и длины. Доступные и доступные для использования записи гарантированно не пересекаются ни с одной другой записью. Наоборот, все недоступные записи (включая ядро/модули) не гарантированно выравнены, и не гарантировано, что они не пересекаются друг с другом.

Элемент входа

ID:

#define LIMINE_ENTRY_POINT_REQUEST { 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_KERNEL_FILE_REQUEST { LIMINE_COMMON_MAGIC, 0xad97e90e83f1ed67, 0x31eb5d1c5ff23b69 }

Запрос:

struct limine_kernel_file_request {
    uint64_t id[4];
    uint64_t revision;
    struct limine_kernel_file_response *response;
};

Ответ:

struct limine_kernel_file_response {
    uint64_t revision;
    struct limine_file *kernel_file;
};
  • kernel_file - Указатель на структуру struct limine_file (см. ниже) для файла ядра.

Функция модуля

ID:

#define LIMINE_MODULE_REQUEST { 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 *cmdline;
    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 — Путь к модулю для загрузки. Этот путь является относительным к местоположению ядра.
  • cmdline — Командная строка для данного модуля.
  • flags — Флаги, изменяющие поведение загрузки модулей:
    • LIMINE_INTERNAL_MODULE_REQUIRED: Ошибка, если запрошенный модуль не найден.
    • LIMINE_INTERNAL_MODULE_COMPRESSED: Модуль сжат методом GZ и должен быть распакован загрузчиком. Это выполняется при версии ответа 2 или выше.

Внутренние модули Limine гарантированно загружаются перед пользователями-определёнными (конфигурационными) модулями, и поэтому они гарантированно будут находиться перед пользователями-определёнными модулями в массиве modules в ответе.

Ответ:

struct limine_module_response {
    uint64_t revision;
    uint64_t module_count;
    struct limine_file **modules;
};
  • module_count — Количество модулей.
  • modules — Указатель на массив указателей на структуры struct limine_file (см. ниже).

Структура файла

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 *cmdline;
    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 — Размер файла.
  • path — Путь файла внутри тома, начинающийся со слеша.
  • cmdline — Командная строка, связанная с файлом.
  • media_type — Тип носителя, на котором находится файл.
  • tftp_ip — Если отличен от 0, это IP адрес сервера TFTP, с которого был загружен файл.
  • tftp_port — Аналогично, но порт.
  • partition_index — Индекс раздела тома, с которого был загружен файл. Если равен 0, значит недействителен или не имеет разделов.
  • mbr_disk_id — Если отличен от 0, это ID диска, с которого был загружен файл, как указано в его MBR.
  • gpt_disk_uuid — Если отличен от 0, это UUID диска, с которого был загружен файл, как указано в его GPT.
  • gpt_part_uuid — Если отличен от 0, это UUID раздела, с которого был загружен файл, как указано в GPT.
  • part_uuid — Если отличен от 0, это UUID файловой системы раздела, с которого был загружен файл.

Функциональность RSDP

ID:

#define LIMINE_RSDP_REQUEST { 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.

Функциональность SMBIOS

ID:

#define LIMINE_SMBIOS_REQUEST { LIMINE_COMMON_MAGIC, 0x7b5e2bdc4bdddfe1, 0x7dbdcbddcdeccdef }

Запрос:

struct limine_smbios_request {
    uint64_t id[4];
    uint64_t revision;
    struct limine_smbios_response *response;
};

Ответ:

struct limine_smbios_response {
    uint64_t revision;
    void *smbios_table;
};
  • smbios_table — Адрес таблицы SMBIOS.

Примечание:

Функциональность SMBIOS позволяет получить доступ к таблице SMBIOS, которая содержит информацию о системе, таких как производитель оборудования, модель устройства, информация о BIOS и многое другое.ID:

#define LIMINE_SMBIOS_REQUEST { 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;
    void *entry_32;
    void *entry_64;
};
  • entry_32 — Адрес точки входа SMBIOS 32-битной архитектуры. NULL, если не существует.
  • entry_64 — Адрес точки входа SMBIOS 64-битной архитектуры. NULL, если не существует.

Функциональность EFI System Table

ID:

#define LIMINE_EFI_SYSTEM_TABLE_REQUEST { 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;
    void *address;
};
  • address — Адрес таблицы EFI системной информации.

Функциональность EFI Memory Map

ID:

#define LIMINE_EFI_MEMMAP_REQUEST { 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(), если смещение HHDM вычтено из memmap.

Функциональность времени загрузки

ID:

#define LIMINE_BOOT_TIME_REQUEST { LIMINE_COMMON_MAGIC, 0x502746e184c088aa, 0xfbc5ec83e6327893 }

Запрос:

struct limine_boot_time_request {
    uint64_t id[4];
    uint64_t revision;
    struct limine_boot_time_response *response;
};

Ответ:

struct limine_boot_time_response {
    uint64_t revision;
    int64_t boot_time;
};
  • boot_time — Время UNIX при загрузке, в секундах, взятое из системного RTC.

Функциональность адреса ядра

ID:

#define LIMINE_KERNEL_ADDRESS_REQUEST { LIMINE_COMMON_MAGIC, 0x71ba76863cc55f63, 0xb2644a48c516a487 }

Запрос:

struct limine_kernel_address_request {
    uint64_t id[4];
    uint64_t revision;
    struct limine_kernel_address_response *response;
};

Ответ:

struct limine_kernel_address_response {
    uint64_t revision;
    uint64_t physical_base;
    uint64_t virtual_base;
};
  • physical_base — Физический базовый адрес ядра.
  • virtual_base — Виртуальный базовый адрес ядра.

Функциональность BLOB дерева устройств

ID:

#define LIMINE_DTB_REQUEST { 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 — Виртуальный указатель на BLOB дерева устройств.

Примечание: Если BLOB дерева устройств не может быть найден, ответ не будет сгенерирован.

Примечание: Информация, содержащаяся в узле /chosen, может не отражать информацию, предоставленную метками загрузчика, и таким образом свойства узла /chosen следует игнорировать.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/input-output-limine.git
git@api.gitlife.ru:oschina-mirror/input-output-limine.git
oschina-mirror
input-output-limine
input-output-limine
stable