grub 폴더에 src 폴더 생성후 hello.c 파일 생성

root@codeServer:~/project/grub# mkdir src && cd $_
root@codeServer:~/project/grub/src# vi hello.c

// hello.c
#define MULTIBOOT_MAGIC 0x1BADB002
#define MULTIBOOT_FLAGS 0x0
#define CHECKSUM -(MULTIBOOT_MAGIC + MULTIBOOT_FLAGS)

__attribute__((section(".multiboot")))
unsigned int header[] = {
    MULTIBOOT_MAGIC,
    MULTIBOOT_FLAGS,
    CHECKSUM
};

void kernel_main() {
    const char *str = "Hello from GRUB\n";
    char *video = (char *)0xb8000;
    int i = 0;

    // 메시지 출력
    while (*str) {
        video[i++] = *str++;
        video[i++] = 0x07;
    }

    // 키 입력 대기
    while (1) {
        unsigned char key;
        asm volatile ("inb $0x64, %0" : "=a"(key));
        if (key & 1) {
            asm volatile ("inb $0x60, %0" : "=a"(key));

            // 디버깅: 키 코드 출력 (2번째 줄 시작)
            video[160] = "0123456789ABCDEF"[key >> 4];
            video[161] = 0x0F;
            video[162] = "0123456789ABCDEF"[key & 0x0F];
            video[163] = 0x0F;

            if (key == 0x1C) break;
        }
    }

    // 종료 메시지 출력
    const char *end = "Shutting down...\n";
    i = 80 * 2 * 2; // 3번째 줄로 이동
    while (*end) {
        video[i++] = *end++;
        video[i++] = 0x0C;
    }

    // QEMU 종료를 위한 I/O 명령 (Bochs/QEMU 연동용)
    asm volatile ("outw %%ax, %%dx" :: "a"(0x2000), "d"(0x604));

    // fallback halt
    asm volatile ("cli; hlt");
}

kernel.ld 파일 생성

root@codeServer:~/project/grub/src# vi kernel.ld

ENTRY(kernel_main)

SECTIONS
{
  . = 1M;

  .multiboot : {
    *(.multiboot)
  }

  .text : {
    *(.text*)
  }

  .data : {
    *(.data*)
  }

  .bss : {
    *(.bss*)
  }
}

 

grub.cfg 파일 수정

root@codeServer:~/project/grub/src# vi ../iso/boot/grub/grub.cfg

set timeout=5
set default=0

menuentry "Hello World (/boot/kernel.elf)" {
    multiboot /boot/kernel.elf
    boot
}

menuentry "Hello World (echo)" {
    echo "Hello from GRUB!"
    echo "Press any key to halt..."
    keystatus --shift --ctrl --alt  # Load keymap support (optional but safe)
    read                            # 대기: 사용자가 키 입력하면 넘어감
    halt
}

 

빌드와 kernel.elf 파일 복사

# 컴파일
gcc -m32 -ffreestanding -c hello.c -o hello.o

# 링커 경고 없이 ELF 만들기
ld -m elf_i386 -T kernel.ld hello.o -o kernel.elf

# 복사
cp kernel.elf ../iso/boot/kernel.elf

 

ISO 생성과 실행

# ISO 생성
cd ..
grub-mkrescue -o hello_grub.iso iso

# 실행
qemu-system-x86_64 -cdrom hello_grub.iso -device isa-debug-exit -curses

실행 화면

Hello World (/boot/kernel.elf) 로 부팅을 하면 아래 화면이 나온다.

A키를 누르면 키 내용이 추가된다.

엔터키를 누르면 Halt가 실행되며 종료된다.

 

최종 디렉터리 구조

root@codeServer:~/project/grub# tree src iso
src
|-- hello.c
|-- hello.o
|-- kernel.elf
`-- kernel.ld
iso
`-- boot
    |-- grub
    |   `-- grub.cfg
    `-- kernel.elf

2 directories, 6 files

 

+ Recent posts