[Booting] Обновление ссылок на изображения

pull/709/head
proninyaroslav 5 years ago
parent fc9b625ee7
commit 050bd8d709

@ -138,7 +138,7 @@ nasm -f bin boot.nasm && qemu-system-x86_64 boot
Вы увидите:
![Простой загрузчик, который печатает только `!`](http://oi60.tinypic.com/2qbwup0.jpg)
![Простой загрузчик, который печатает только `!`](images/simple_bootloader.png)
В этом примере мы можем видеть, что код будет выполнен в 16-битном режиме реальных адресов и начнёт выполнение с адреса `0x7c00`. После запуска он вызывает прерывание [0x10](http://www.ctyme.com/intr/rb-0106.htm), которое просто печатает символ `!`. Оставшиеся 510 байт заполняются нулями, и код заканчивается двумя магическими байтами `0xaa` и `0x55`.
@ -247,7 +247,7 @@ X + sizeof(KernelBootSector) + 1
```
где `X` - это адрес загруженного сектора загрузки ядра. В моем случае `X` это `0x10000`, как мы можем видеть в дампе памяти:
![Первый адрес ядра](http://oi57.tinypic.com/16bkco2.jpg)
![Первый адрес ядра](images/kernel_first_address.png)
Сейчас загрузчик поместил ядро Linux в память, заполнил поля заголовка, а затем переключился на него. Теперь мы можем перейти непосредственно к коду настройки ядра.
@ -263,7 +263,7 @@ qemu-system-x86_64 vmlinuz-3.18-generic
то увидите:
![Попытка использовать vmlinuz в qemu](http://oi60.tinypic.com/r02xkz.jpg)
![Попытка использовать vmlinuz в qemu](images/try_vmlinuz_in_qemu.png)
На самом деле, `header.S` начинается с [MZ](https://en.wikipedia.org/wiki/DOS_MZ_executable) (см. картинку выше), вывода сообщения об ошибке и [PE](https://en.wikipedia.org/wiki/Portable_Executable) заголовка:
@ -403,7 +403,7 @@ _start:
Здесь мы видим выравнивание сегмента `dx` (содержащего значение `sp`, полученное загрузчиком) до 4 байт и проверку - является ли полученное значение нулём. Если ноль, то помещаем `0xfffx` (выровненный до `4` байт адрес до максимального значения сегмента в 64 Кб) в `dx`. Если не ноль, продолжаем использовать `sp`, полученный от загрузчика (в моём случае `0xf7f4`). После этого мы помещаем значение `ax` в `ss`, который хранит корректный адрес сегмента `0x1000` и устанавливает корректное значение `sp`. Теперь мы имеем корректный стек:
![стек](http://oi58.tinypic.com/16iwcis.jpg)
![стек](images/stack1.png)
* Второй сценарий (когда `ss` != `ds`). Во-первых, помещаем значение [_end](https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/setup.ld#L52) (адрес окончания кода настройки) в `dx` и проверяем поле заголовка `loadflags` инструкцией `testb`, чтобы понять, можем ли мы использовать кучу (heap). [loadflags](https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/header.S#L321) является заголовком с битовой маской, который определён как:
@ -427,11 +427,11 @@ _start:
```
Если бит `CAN_USE_HEAP` установлен, мы помещаем `heap_end_ptr` в `dx` (который указывает на `_end`) и добавляем к нему `STACK_SIZE` (минимальный размер стека, `512` байт). После этого, если `dx` без переноса (будет без переноса, поскольку `dx = _end + 512`), переходим на метку `2` (как в предыдущем случае) и создаём корректный стек.
![стек](http://oi62.tinypic.com/dr7b5w.jpg)
![стек](images/stack2.png)
* Если флаг `CAN_USE_HEAP` не установлен, мы просто используем минимальный стек от `_end` до `_end + STACK_SIZE`:
![минимальный стек](http://oi60.tinypic.com/28w051y.jpg)
![минимальный стек](images/minimal_stack.png)
Настройка BSS
--------------------------------------------------------------------------------
@ -458,7 +458,7 @@ _start:
```
Во-первых, адрес [__bss_start](https://github.com/torvalds/linux/blob/v4.16/arch/x86/boot/setup.ld#L47) помещается в `di`. Далее, адрес `_end + 3` (+3 - выравнивает до 4 байт) помещается в `cx`. Регистр `eax` очищается (с помощью инструкции `xor`), а размер секции BSS (`cx`-`di`) вычисляется и помещается в `cx`. Затем `cx` делится на 4 (размер 'слова' (англ. word)), а инструкция `stosl` используется повторно, сохраняя значение `eax` (ноль) в адрес, на который указывает `di`, автоматически увеличивая `di` на 4 (это продолжается до тех пор, пока `cx` не достигнет нуля). Эффект от этого кода в том, что теперь все 'слова' в памяти от `__bss_start` до `_end` заполнены нулями:
![bss](http://oi59.tinypic.com/29m2eyr.jpg)
![bss](images/bss.png)
Переход к основному коду
--------------------------------------------------------------------------------

@ -166,7 +166,7 @@ lgdt gdt
Схематично это будет выглядеть следующим образом:
![линейный адрес](http://oi62.tinypic.com/2yo369v.jpg)
![линейный адрес](images/linear_address.png)
Алгоритм перехода из режима реальных адресов в защищённый режим:

@ -40,7 +40,7 @@ vga=<mode>
Таким образом, мы можем добавить параметр `vga` в конфигурационный файл GRUB (или любого другого загрузчика) и он передаст его в командную строку ядра. Как говорится в описании, этот параметр может иметь разные значения. Например, это может быть целым числом `0xFFFD` или `ask`. Если передать `ask` в `vga`, вы увидите примерно такое меню:
![video mode setup menu](http://oi59.tinypic.com/ejcz81.jpg)
![video mode setup menu](images/video_mode_setup_menu.png)
которое попросит выбрать видеорежим. Мы посмотрим на его реализацию, но перед этим рассмотрим некоторые другие вещи.

Loading…
Cancel
Save