makefilekernelosdevgrub2

How to load userland with grub in this case?


I learn usermode by tutorial. In the tutorial they built kernel image by this code:

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

and build userland by this code:

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

They use bochs and custom bootloader and load kernel and user mode by this code:

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

But I use grub for my kernel. And I run iso with qemu. I also use gas instead of nasm.

Making iso from my Makefile(like in osdev tutorials):

...
$(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

How to load userland with grub? Or I need write some code in kernel to load user processes?

github link: https://github.com/JustVic/kernel_usermode


Solution

  • grub is intended to get your OS loaded, and then the OS is supposed to do the heavy lifting of exec'ing user.bin. I believe your OS sets up a slot for one process (init_process/set_process_entry), sets up its stack and page map, and would then launch user.bin with launch(). I don't see lots of great device drivers in your github :-@), so I think you need to get grub to load your user.bin for you by one of the available methods for loading files and then get the load address communicated to launch(). In effect, you need the equivalent of Linux's /sbin/init all precompiled, prelinked and loaded into physical memory so you can just pstart it.

    Once you've precompiled/prelinked your user.bin, try one of these methods to add a grub entry to load it:

    1. set root=(cd0) (if you're supplying user.bin in an ISO file) and use the chainloader --force command to load it into memory without trying to verify its signature or do anything else "smart" with it; or
    2. Make a custom grub module to do this that you can invoke with insmod; or
    3. Cheat by using gdb to load the file into memory, and then let the OS know at what address it got loaded: SO tip to load file into memory via gdb.

    Once you have some more device and process/thread support in your OS, you can do this the "normal" way by passing something like init=/etc/user.bin on the kernel command line so the kernel can mmap and exec it. Supporting multiple processes with even a dumb scheduler would be great since then you could actually keep the OS going rather than exec'ing into user.bin and kinda ending there.

    Best tutorial I could find for you to finish up is here. By good fortune there is a nice section in there about making a grub module for exactly this sort of thing.