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
'운영체제 > 리눅스' 카테고리의 다른 글
| [우분투 커널 빌드] 6.8.0-59 -> 6.8.0-60 (0) | 2025.09.12 |
|---|---|
| [리눅스커널] (0) | 2025.09.05 |
| [GRUB] 1. 빌드와 테스트 (1) | 2025.08.01 |
| [리눅스_커널 디버깅] 6. 인터럽트 (rpi4 6.6.x) (0) | 2025.05.16 |
| [리눅스_커널 디버깅] 5. 프로세스 디버깅 (rpi4 6.6.x) (1) | 2025.05.09 |