mirror of
https://github.com/0xAX/linux-insides.git
synced 2024-11-16 04:59:13 +00:00
Update linux-bootstrap-3.md
This commit is contained in:
parent
7d015af76e
commit
92af9fc9d8
@ -6,8 +6,8 @@
|
||||
|
||||
Это третья часть серии `Процесса загрузки ядра`. В предыдущей [части](linux-bootstrap-2.md#kernel-booting-process-part-2) мы остановились прямо перед вызовом функции `set_video` из [main.c](https://github.com/torvalds/linux/blob/16f73eb02d7e1765ccab3d2018e0bd98eb93d973/arch/x86/boot/main.c#L181). В этой части мы увидим:
|
||||
|
||||
- Инициализацию видеорежима в коде настройки ядра,
|
||||
- подготовку перед переключением в защищённый режим,
|
||||
- инициализацию видеорежима в коде настройки ядра,
|
||||
- подготовку, сделанную перед переключением в защищённый режим,
|
||||
- переход в защищённый режим
|
||||
|
||||
**ПРИМЕЧАНИЕ:** если вы ничего не знаете о защищённом режиме, вы можете найти некоторую информацию о нём в предыдущей [части](linux-bootstrap-2.md#protected-mode). Также есть несколько [ссылок](linux-bootstrap-2.md#links), которые могут вам помочь.
|
||||
@ -38,7 +38,7 @@ vga=<mode>
|
||||
парсинга командной строки.
|
||||
```
|
||||
|
||||
Таким образом, мы можем добавить параметр `vga` в конфигурационный файл GRUB или любого другого загрузчика и он передаст его в командную строку ядра. Как говорится в описании, этот параметр может иметь разные значения. Например, это может быть целым числом `0xFFFD` или `ask`. Если передать `ask` в `vga`, вы увидите примерно такое меню:
|
||||
Таким образом, мы можем добавить параметр `vga` в конфигурационный файл GRUB (или любого другого загрузчика) и он передаст его в командную строку ядра. Как говорится в описании, этот параметр может иметь разные значения. Например, это может быть целым числом `0xFFFD` или `ask`. Если передать `ask` в `vga`, вы увидите примерно такое меню:
|
||||
|
||||
![video mode setup menu](http://oi59.tinypic.com/ejcz81.jpg)
|
||||
|
||||
@ -82,9 +82,9 @@ API кучи
|
||||
|
||||
предназначен для выделения кучи. Он вызывает внутреннюю функцию `__get_heap` с тремя параметрами:
|
||||
|
||||
* размер типа в байтах, который должен быть выделен
|
||||
* `__alignof__(type)` показывает, как переменные этого типа выровнены
|
||||
* `n` говорит о том, сколько элементов нужно выделить
|
||||
* размер типа данных, который должен быть выделен
|
||||
* `__alignof__(type)` определяет, как переменные этого типа должны быть выровнены
|
||||
* `n` определяет сколько элементов нужно выделить
|
||||
|
||||
Реализация `__get_heap`:
|
||||
|
||||
@ -117,7 +117,7 @@ static inline bool heap_free(size_t n)
|
||||
}
|
||||
```
|
||||
|
||||
которая вычитает значение `HEAP` из `heap_end` (мы вычисляли это в предыдущей [части](linux-bootstrap-2.md)) и возвращает 1, если имеется достаточно памяти для `n`.
|
||||
которая вычитает значение указателя `HEAP` из `heap_end` (мы вычисляли это в предыдущей [части](linux-bootstrap-2.md)) и возвращает 1, если имеется достаточно памяти для `n`.
|
||||
|
||||
На этом всё. Теперь у нас есть простой API для кучи и можем перейти к настройке видеорежима.
|
||||
|
||||
@ -175,7 +175,7 @@ if (!heap_free(saved.x*saved.y*sizeof(u16)+512))
|
||||
|
||||
и если места в куче достаточно, выделяет его и сохраняет в нём `saved_screen`.
|
||||
|
||||
Следующий вызов - `probe_cards(0)` из [arch/x86/boot/video-mode.c](https://github.com/0xAX/linux/blob/master/arch/x86/boot/video-mode.c#L33). Она проходит по всем video_cards и собирает количество режимов, предоставляемых картой. И вот здесь интересный момент. Мы можем видеть цикл:
|
||||
Следующий вызов - `probe_cards(0)` из [arch/x86/boot/video-mode.c](https://github.com/0xAX/linux/blob/master/arch/x86/boot/video-mode.c#L33). Она проходит по всем `video_cards` и собирает количество режимов, предоставляемых картой. И вот здесь интересный момент. Мы можем видеть цикл:
|
||||
|
||||
```C
|
||||
for (card = video_cards; card < video_cards_end; card++) {
|
||||
@ -272,7 +272,7 @@ static int vga_set_mode(struct mode_info *mode)
|
||||
|
||||
Далее вызывается `vesa_store_edid`. Эта функция сохраняет информацию о [EDID](https://en.wikipedia.org/wiki/Extended_Display_Identification_Data) (**E**xtended **D**isplay **I**dentification **D**ata) для использования ядром. После этого снова вызывается `store_mode_params`. И наконец, если установлен `do_restore`, экран восстанавливается в предыдущее состояние.
|
||||
|
||||
Теперь, когда видеорежим установлен, мы можем переключится в защищённый режим.
|
||||
Сделав это, мы завершаем настройку видеорежима и мы можем переключится в защищённый режим.
|
||||
|
||||
Последняя подготовка перед переходом в защищённый режим
|
||||
--------------------------------------------------------------------------------
|
||||
@ -336,7 +336,7 @@ static int a20_test(int loops)
|
||||
|
||||
В первую очередь мы устанавливаем регистр `FS` в `0x0000` и регистр `GS` в `0xffff`. Далее мы читаем значение по адресу `A20_TEST_ADDR` (`0x200`) и сохраняем его в переменную `saved` и `ctr`.
|
||||
|
||||
После этого мы записываем обновлённое значение `ctr` в `fs:gs` с помощью функции `wrfs32`, совершаем задержку в 1 мс, а затем читаем значение из регистра `GS` по адресу `A20_TEST_ADDR+0x10`. Если это не ноль, то линия A20 уже включена. Если линия A20 отключена, мы пытаемся включить её с помощью других методов, которые вы можете найти в `a20.c`. Например, с помощью вызова BIOS прерывания `0x15` с `AH=0x2041` и т.д.
|
||||
После этого мы записываем обновлённое значение `ctr` в `fs:gs` с помощью функции `wrfs32`, совершаем задержку в 1 мс, а затем читаем значение из регистра `GS` по адресу `A20_TEST_ADDR+0x10`. Если это не ноль, то линия A20 уже включена. Если линия A20 отключена, мы пытаемся включить её с помощью других методов, которые вы можете найти в `a20.c`. Например, это может быть сделано с помощью вызова BIOS прерывания `0x15` с `AH=0x2041` и т.д.
|
||||
|
||||
Если функция `enabled_a20` завершается неудачей, выводится сообщение об ошибке и вызывается функция `die`. Вы можете вспомнить её из первого файла исходного кода, откуда мы начали - [arch/x86/boot/header.S](https://github.com/torvalds/linux/blob/16f73eb02d7e1765ccab3d2018e0bd98eb93d973/arch/x86/boot/header.S):
|
||||
|
||||
@ -429,7 +429,7 @@ int main(void)
|
||||
}
|
||||
```
|
||||
|
||||
Технически, структура, которая содержит одно поле типа `int`, должна иметь размер 4 байта, но так как это `aligned` структура, она будет иметь размер 16 байт:
|
||||
Технически, структура, которая содержит одно поле типа `int`, должна иметь размер 4 байта, но для `aligned` структуры потребуется 16 байт для хранения в памяти:
|
||||
|
||||
```
|
||||
$ gcc test.c -o test && test
|
||||
@ -534,7 +534,7 @@ movl %edx, %cr0
|
||||
* `0x66` - префикс размера операнда, который позволяет смешивать как 16-битный, так и 32-битный код,
|
||||
* `0xea` - опкод инструкции перехода,
|
||||
* `in_pm32` - смещение сегмента
|
||||
* `__BOOT_CS` - сегмент кода.
|
||||
* `__BOOT_CS` - сегмент кода, на который мы хотим перейти.
|
||||
|
||||
После этого мы наконец-то в защищённом режиме:
|
||||
|
||||
@ -576,7 +576,7 @@ jmpl *%eax
|
||||
Заключение
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Это конец третьей части о внутренностях ядра Linux. В следующей части мы рассмотрим первые шаги в защищённом режиме и переход в long mode.
|
||||
Это конец третьей части о внутренностях ядра Linux. В следующей части мы рассмотрим первые шаги в защищённом режиме и переход в [long mode](https://en.wikipedia.org/wiki/Long_mode).
|
||||
|
||||
**От переводчика: пожалуйста, имейте в виду, что английский - не мой родной язык, и я очень извиняюсь за возможные неудобства. Если вы найдёте какие-либо ошибки или неточности в переводе, пожалуйста, пришлите pull request в [linux-insides-ru](https://github.com/proninyaroslav/linux-insides-ru).**
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user