在这种情况下如何使用 grub 加载 userland?
How to load userland with grub in this case?
我通过教程学习用户模式。
在教程中,他们通过以下代码构建内核映像:
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。我用 qemu 运行 iso。我也用 gas 代替 nasm.
从我的 Makefile 制作 iso(就像在 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 加载 userland?或者我需要在内核中写一些代码来加载用户进程?
github link: https://github.com/JustVic/kernel_usermode
grub 旨在让您的 OS 加载,然后 OS 应该执行执行 user.bin 的繁重工作。我相信您的 OS 为一个进程 (init_process/set_process_entry) 设置了一个插槽,设置了它的堆栈和页面映射,然后将使用 launch() 启动 user.bin。我在你的 github 中没有看到很多很棒的设备驱动程序 :-@),所以我认为你需要让 grub 通过一种可用的加载文件的方法来为你加载你的 user.bin 和然后获取传送给 launch() 的加载地址。实际上,您需要相当于 Linux 的 /sbin/init
所有预编译、预链接并加载到物理内存中,这样您就可以直接启动它。
一旦您 precompiled/prelinked 您的 user.bin,请尝试使用以下方法之一添加 grub 条目以加载它:
- set root=(cd0)(如果您在 ISO 文件中提供 user.bin)并使用
chainloader --force
命令将其加载到内存中,而不尝试验证其签名或做任何事情否则“聪明”;或
- 制作一个自定义的 grub 模块来执行此操作,您可以使用
insmod
调用它;或
- 通过使用 gdb 将文件加载到内存中作弊,然后让 OS 知道它加载的地址:SO tip to load file into memory via gdb.
一旦你的 OS 中有了更多的设备和 process/thread 支持,你就可以通过在内核命令行上传递 init=/etc/user.bin
之类的内容来以“正常”方式执行此操作内核可以映射并执行它。即使是一个愚蠢的调度程序也支持多个进程会很棒,因为那时你实际上可以让 OS 继续运行而不是执行到 user.bin 并有点结束。
我能找到的最好的教程是 here。幸运的是,其中有一个很好的部分是关于为这类事情制作一个 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。我用 qemu 运行 iso。我也用 gas 代替 nasm.
从我的 Makefile 制作 iso(就像在 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 加载 userland?或者我需要在内核中写一些代码来加载用户进程?
github link: https://github.com/JustVic/kernel_usermode
grub 旨在让您的 OS 加载,然后 OS 应该执行执行 user.bin 的繁重工作。我相信您的 OS 为一个进程 (init_process/set_process_entry) 设置了一个插槽,设置了它的堆栈和页面映射,然后将使用 launch() 启动 user.bin。我在你的 github 中没有看到很多很棒的设备驱动程序 :-@),所以我认为你需要让 grub 通过一种可用的加载文件的方法来为你加载你的 user.bin 和然后获取传送给 launch() 的加载地址。实际上,您需要相当于 Linux 的 /sbin/init
所有预编译、预链接并加载到物理内存中,这样您就可以直接启动它。
一旦您 precompiled/prelinked 您的 user.bin,请尝试使用以下方法之一添加 grub 条目以加载它:
- set root=(cd0)(如果您在 ISO 文件中提供 user.bin)并使用
chainloader --force
命令将其加载到内存中,而不尝试验证其签名或做任何事情否则“聪明”;或 - 制作一个自定义的 grub 模块来执行此操作,您可以使用
insmod
调用它;或 - 通过使用 gdb 将文件加载到内存中作弊,然后让 OS 知道它加载的地址:SO tip to load file into memory via gdb.
一旦你的 OS 中有了更多的设备和 process/thread 支持,你就可以通过在内核命令行上传递 init=/etc/user.bin
之类的内容来以“正常”方式执行此操作内核可以映射并执行它。即使是一个愚蠢的调度程序也支持多个进程会很棒,因为那时你实际上可以让 OS 继续运行而不是执行到 user.bin 并有点结束。
我能找到的最好的教程是 here。幸运的是,其中有一个很好的部分是关于为这类事情制作一个 grub 模块。