Как в этом случае загрузить пользовательское пространство с помощью grub?

Я изучаю пользовательский режим по учебнику. В туториале они собрали образ ядра по этому коду:

nasm -f bin -o boot.bin boot.asm
nasm -f bin -o loader.bin loader.asm
nasm -f elf64 -o kernel.o kernel.asm
nasm -f elf64 -o trapa.o trap.asm
nasm -f elf64 -o liba.o lib.asm
gcc -std=c99 -mcmodel=large -ffreestanding -fno-stack-protector -mno-red-zone -c main.c 
gcc -std=c99 -mcmodel=large -ffreestanding -fno-stack-protector -mno-red-zone -c trap.c 
gcc -std=c99 -mcmodel=large -ffreestanding -fno-stack-protector -mno-red-zone -c print.c 
gcc -std=c99 -mcmodel=large -ffreestanding -fno-stack-protector -mno-red-zone -c debug.c 
gcc -std=c99 -mcmodel=large -ffreestanding -fno-stack-protector -mno-red-zone -c memory.c 
gcc -std=c99 -mcmodel=large -ffreestanding -fno-stack-protector -mno-red-zone -c process.c 
gcc -std=c99 -mcmodel=large -ffreestanding -fno-stack-protector -mno-red-zone -c syscall.c 
ld -nostdlib -T link.lds -o kernel kernel.o main.o trapa.o trap.o liba.o print.o debug.o memory.o process.o syscall.o
objcopy -O binary kernel kernel.bin 
dd if=boot.bin of=boot.img bs=512 count=1 conv=notrunc
dd if=loader.bin of=boot.img bs=512 count=5 seek=1 conv=notrunc
dd if=kernel.bin of=boot.img bs=512 count=100 seek=6 conv=notrunc
dd if=user.bin of=boot.img bs=512 count=10 seek=106 conv=notrunc

и создайте пользовательское пространство по этому коду:

nasm -f elf64 -o start.o start.asm
gcc -std=c99 -mcmodel=large -ffreestanding -fno-stack-protector -mno-red-zone -c main.c
ld -nostdlib -Tlink.lds -o user start.o main.o lib.a 
objcopy -O binary user user.bin

Они используют bochs и пользовательский загрузчик и загружают ядро ​​​​и пользовательский режим с помощью этого кода:

LoadKernel:
    mov si,ReadPacket
    mov word[si],0x10
    mov word[si+2],100
    mov word[si+4],0
    mov word[si+6],0x1000
    mov dword[si+8],6
    mov dword[si+0xc],0
    mov dl,[DriveId]
    mov ah,0x42
    int 0x13
    jc  ReadError

LoadUser:
    mov si,ReadPacket
    mov word[si],0x10
    mov word[si+2],10
    mov word[si+4],0
    mov word[si+6],0x2000
    mov dword[si+8],106
    mov dword[si+0xc],0
    mov dl,[DriveId]
    mov ah,0x42
    int 0x13
    jc  ReadError

Но я использую grub для своего ядра. И я запускаю iso с qemu. Я также использую газ вместо nasm.

Создание iso из моего Makefile (как в учебниках по osdev):

...
$(ISO_FILE): kernel
    mkdir -p iso/boot/grub
    cp grub.cfg iso/boot/grub/
    cp kernel/kernel iso/boot/
    $(GRUB_MKRESCUE) -o $(ISO_FILE) iso

Как загрузить пользовательское пространство с помощью grub? Или мне нужно написать код в ядре для загрузки пользовательских процессов?

ссылка на github: https://github.com/JustVic/kernel_usermode


person JustOneMan    schedule 04.07.2021    source источник


Ответы (1)


grub предназначен для загрузки вашей ОС, а затем ОС должна выполнять тяжелую работу по выполнению user.bin. Я полагаю, что ваша ОС устанавливает слот для одного процесса (init_process/set_process_entry), устанавливает его стек и карту страниц, а затем запускает user.bin с помощью launch(). Я не вижу много отличных драйверов устройств в вашем github :-@), поэтому я думаю, вам нужно заставить grub загрузить ваш user.bin одним из доступных методов загрузки файлов, а затем получить адрес загрузки. запускать(). По сути, вам нужен эквивалент Linux /sbin/init, предварительно скомпилированный, предварительно связанный и загруженный в физическую память, чтобы вы могли просто запустить его.

После того, как вы предварительно скомпилировали / предварительно связали свой user.bin, попробуйте один из этих методов, чтобы добавить запись grub для его загрузки:

  1. установите root=(cd0) (если вы предоставляете user.bin в файле ISO) и используйте команду chainloader --force, чтобы загрузить его в память, не пытаясь проверить его подпись или сделать с ним что-то еще умное; или же
  2. Создайте для этого собственный модуль grub, который вы можете вызывать с помощью insmod; или же
  3. Обманите, используя gdb, чтобы загрузить файл в память, а затем сообщите ОС, по какому адресу он был загружен: Советуем загрузить файл в память через gdb.

Как только в вашей ОС появится поддержка устройств и процессов/потоков, вы можете сделать это обычным способом, передав что-то вроде init=/etc/user.bin в командной строке ядра, чтобы ядро ​​могло выполнить mmap и выполнить его. Поддержка нескольких процессов даже с тупым планировщиком была бы отличной, поскольку тогда вы действительно могли бы поддерживать работу ОС, а не запускать ее в user.bin и заканчивать там.

Лучшее руководство, которое я смог найти для вас, это здесь. К счастью, там есть хороший раздел о создании модуля grub именно для таких вещей.

Если этот ответ поможет вам или просто приведет вас к примерному положению, рассмотрите возможность пометить его как принятый. Спасибо и удачи в получении user.bin!

person Frank Hoeflich    schedule 07.07.2021