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
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:
chainloader --force
command to load it into memory without trying to verify its signature or do anything else "smart" with it; orinsmod
; orOnce 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.