Fix Linux kernel handoff: GDT selectors, E820 map, jump_linux#1
Merged
Conversation
- GDT: add dummy descriptor so code/data land at selectors 0x10/0x18 as required by the Linux 32-bit boot protocol (were 0x08/0x10). - Stage 1: collect BIOS E820 memory map via int 0x15/0xE820 and stash it at 0x4000; Stage 2 copies it into the zeropage (0x1E8 / 0x2D0). Without a memory map the kernel paniced during memory init. - jump_linux: zero ebp/edi/ebx and move the stack to 0x80000 so it no longer overlaps boot_params at 0x90000. Debian 12 (ext2, no GRUB) now boots to userspace in QEMU.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Что исправлено
Загрузчик доходил до передачи управления ядру, но ядро молча зависало
сразу после "Booting Linux". Найдено и исправлено три причины:
1. GDT не по Linux boot protocol
Протокол требует селекторы __BOOT_CS = 0x10 и __BOOT_DS = 0x18.
В GDT код был на 0x08, данные на 0x10 — когда ядро перезагружало
сегменты значением 0x18, попадало на несуществующий дескриптор.
Добавлен фиктивный дескриптор, чтобы сдвинуть код на 0x10, данные на 0x18.
2. Не заполнялась e820-карта памяти
Без карты памяти ядро паниковало при инициализации MM
("Failed to allocate ... for node 0 memory map"). Stage 1 теперь
собирает карту через BIOS int 0x15/0xE820 и складывает по адресу 0x4000;
Stage 2 копирует её в zeropage (число записей -> 0x1E8, таблица -> 0x2D0).
3. Стек в jump_linux перекрывал boot_params
Стек ставился на 0x90000 — прямо поверх boot_params. Перенесён на 0x80000.
Также обнулены ebp/edi/ebx, как требует протокол.
Тестирование
Debian 12 (i386, ext2-раздел, установлен без GRUB) успешно загружается
в QEMU до приглашения логина:
qemu-system-i386 -m 512M -drive format=raw,file=debian-ext2.imgЗагрузчик находит /boot/vmlinuz и /boot/initrd.img на ext2, грузит ядро
и initrd, ядро стартует, монтирует корень, поднимается systemd.