如何使用内核创建可引导的CD映像?
我有一个内核,要引导,我使用命令如何使用内核创建可引导的CD映像?,c,assembly,operating-system,kernel,nasm,C,Assembly,Operating System,Kernel,Nasm,我有一个内核,要引导,我使用命令qemu-system-i386-kernel-kernel.bin。是否有任何方法可以创建可引导磁盘映像以使用qemu-system-i386-cdrom CD.iso引导 我在linux中使用以下命令编译的代码: nasm -f elf32 kernel.asm -o kernelasm.o gcc -m32 -c kernel.c -o kernelc.o ld -m elf_i386 -T link.ld -o kernel.bin kernelasm.o
qemu-system-i386-kernel-kernel.bin
。是否有任何方法可以创建可引导磁盘映像以使用qemu-system-i386-cdrom CD.iso引导
我在linux中使用以下命令编译的代码:
nasm -f elf32 kernel.asm -o kernelasm.o
gcc -m32 -c kernel.c -o kernelc.o
ld -m elf_i386 -T link.ld -o kernel.bin kernelasm.o kernelc.o
然后使用qemu-system-i386-kernel kernel.bin引导
代码:
kernel.asm:
[BITS 32]
SECTION .text
align 4
dd 0x1BADB002
dd 0x00
dd - (0x1BADB002 + 0x00)
global start
global keyboard_handler
global read_port
global write_port
global load_idt
extern kmain
extern keyboard_handler_main
read_port:
mov edx, [esp + 4]
in al, dx
ret
write_port:
mov edx, [esp + 4]
mov al, [esp + 4 + 4]
out dx, al
ret
load_idt:
mov edx, [esp + 4]
lidt [edx]
sti
ret
keyboard_handler:
call keyboard_handler_main
iretd
start:
cli
mov esp, stack_space
call kmain
hlt
section .bss
resb 8192
stack_space:
kernel.c:
#include "keyboard_map.h"
#define LINES 25
#define COLUMNS_IN_LINE 80
#define BYTES_FOR_EACH_ELEMENT 2
#define SCREENSIZE BYTES_FOR_EACH_ELEMENT * COLUMNS_IN_LINE * LINES
#define KEYBOARD_DATA_PORT 0x60
#define KEYBOARD_STATUS_PORT 0x64
#define IDT_SIZE 256
#define INTERRUPT_GATE 0x8e
#define KERNEL_CODE_SEGMENT_OFFSET 0x08
#define ENTER_KEY_CODE 0x1C
extern unsigned char keyboard_map[128];
extern void keyboard_handler(void);
extern char read_port(unsigned short port);
extern void write_port(unsigned short port, unsigned char data);
extern void load_idt(unsigned long *idt_ptr);
unsigned int current_loc = 0;
char *vidptr = (char*)0xb8000;
struct IDT_entry {
unsigned short int offset_lowerbits;
unsigned short int selector;
unsigned char zero;
unsigned char type_attr;
unsigned short int offset_higherbits;
};
struct IDT_entry IDT[IDT_SIZE];
void idt_init(void)
{
unsigned long keyboard_address;
unsigned long idt_address;
unsigned long idt_ptr[2];
keyboard_address = (unsigned long)keyboard_handler;
IDT[0x21].offset_lowerbits = keyboard_address & 0xffff;
IDT[0x21].selector = KERNEL_CODE_SEGMENT_OFFSET;
IDT[0x21].zero = 0;
IDT[0x21].type_attr = INTERRUPT_GATE;
IDT[0x21].offset_higherbits = (keyboard_address & 0xffff0000) >> 16;
write_port(0x20 , 0x11);
write_port(0xA0 , 0x11);
write_port(0x21 , 0x20);
write_port(0xA1 , 0x28);
write_port(0x21 , 0x00);
write_port(0xA1 , 0x00);
write_port(0x21 , 0x01);
write_port(0xA1 , 0x01);
write_port(0x21 , 0xff);
write_port(0xA1 , 0xff);
idt_address = (unsigned long)IDT ;
idt_ptr[0] = (sizeof (struct IDT_entry) * IDT_SIZE) + ((idt_address & 0xffff) << 16);
idt_ptr[1] = idt_address >> 16 ;
load_idt(idt_ptr);
}
void kb_init(void)
{
write_port(0x21 , 0xFD);
}
void kprint(const char *str)
{
unsigned int i = 0;
while (str[i] != '\0') {
vidptr[current_loc++] = str[i++];
vidptr[current_loc++] = 0x07;
}
}
void kprint_newline(void)
{
unsigned int line_size = BYTES_FOR_EACH_ELEMENT * COLUMNS_IN_LINE;
current_loc = current_loc + (line_size - current_loc % (line_size));
}
void clear_screen(void)
{
unsigned int i = 0;
while (i < SCREENSIZE) {
vidptr[i++] = ' ';
vidptr[i++] = 0x07;
}
}
void keyboard_handler_main(void)
{
unsigned char status;
char keycode;
write_port(0x20, 0x20);
status = read_port(KEYBOARD_STATUS_PORT);
if (status & 0x01) {
keycode = read_port(KEYBOARD_DATA_PORT);
if(keycode < 0)
return;
if(keycode == ENTER_KEY_CODE) {
kprint_newline();
return;
}
vidptr[current_loc++] = keyboard_map[(unsigned char) keycode];
vidptr[current_loc++] = 0x07;
}
}
void kmain(void)
{
const char *str = "my first kernel with keyboard support";
clear_screen();
kprint(str);
kprint_newline();
kprint_newline();
idt_init();
kb_init();
while(1);
}
首先,我向您介绍引导过程的基本原理。实际上,当您运行命令qemu-system-i386-kernel kernel.bin
qemu将内核二进制文件加载到内存中的0x7c000位置,从该位置继续引导。
如果你想从ISO启动,那么你必须告诉BIOS在我的ISO中有一个可启动映像(标记启动标志),并给它正确的指令来启动你的内核。
怎么做?
您必须设置一个引导加载程序,它可以由BIOS在0x7c000加载,稍后它会将内核映像加载到内存中并跳转到内核入口点。
因此,请将ISO标记为活动(引导标志)并添加引导加载程序代码
我可以看到您已经有了安装多引导入口点代码
align 4
dd 0x1BADB002
dd 0x00
dd - (0x1BADB002 + 0x00)
您可以从这里阅读有关设置grub启动链的更多信息
您还可以使用syslinux引导加载程序
syslinux
将isolinux.bin、syslinux.cfg和mboot.c32复制到内核二进制映像的构建路径。
配置syslinux.cfg并执行以下命令
mkisofs.exe -o %OUTPUT_DIR%\%BUILD_NAME%.iso -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table %ISO_DIR%
环顾“El Torito”标准可能的副本
align 4
dd 0x1BADB002
dd 0x00
dd - (0x1BADB002 + 0x00)
mkisofs.exe -o %OUTPUT_DIR%\%BUILD_NAME%.iso -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table %ISO_DIR%