update qemu study
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
; mybios_ssh.asm
|
||||
[BITS 16]
|
||||
[ORG 0]
|
||||
|
||||
bios_start:
|
||||
; 1. 세그먼트 초기화
|
||||
mov ax, 0xF000
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
xor ax, ax
|
||||
mov ss, ax
|
||||
mov sp, 0x7C00
|
||||
|
||||
; 2. 시리얼 포트 초기화 (가장 중요!)
|
||||
call init_serial
|
||||
|
||||
; 3. 부팅 메시지 출력
|
||||
mov si, msg_boot
|
||||
call print_serial
|
||||
|
||||
; 4. 메인 루프 (입력 대기)
|
||||
mov si, msg_menu
|
||||
call print_serial
|
||||
|
||||
main_loop:
|
||||
; --- Heartbeat (살아있음을 표시) ---
|
||||
; 입력이 없어도 멈춘 게 아니라는 걸 보여주기 위해 점(.)을 찍을 수도 있지만,
|
||||
; 너무 지저분해지니 생략하고 입력만 기다립니다.
|
||||
|
||||
; [입력 확인] 0x3FD 포트의 0번 비트가 1이면 데이터가 온 것임
|
||||
mov dx, 0x3FD
|
||||
in al, dx
|
||||
test al, 1
|
||||
jz main_loop ; 데이터 없으면 계속 뺑뺑이(Loop)
|
||||
|
||||
; [데이터 읽기] 0x3F8 포트에서 읽음
|
||||
mov dx, 0x3F8
|
||||
in al, dx
|
||||
|
||||
; [내가 누른 키 화면에 보여주기 (Echo)]
|
||||
; 이게 없으면 내가 뭘 눌렀는지 터미널에 안 보임!
|
||||
out dx, al
|
||||
|
||||
; [키 판별]
|
||||
cmp al, '1'
|
||||
je action_shutdown
|
||||
|
||||
cmp al, '2'
|
||||
je action_reboot
|
||||
|
||||
jmp main_loop
|
||||
|
||||
; ===========================================================
|
||||
; [Actions]
|
||||
; ===========================================================
|
||||
|
||||
action_shutdown:
|
||||
mov si, msg_bye
|
||||
call print_serial
|
||||
|
||||
; PIIX4 ACPI Shutdown (Power Off)
|
||||
; 1. I/O Enable
|
||||
mov dx, 0xCF8
|
||||
mov eax, 0x80000B04
|
||||
out dx, eax
|
||||
mov dx, 0xCFC
|
||||
mov eax, 0x0001
|
||||
out dx, eax
|
||||
|
||||
; 2. PMBA -> 0xB000
|
||||
mov dx, 0xCF8
|
||||
mov eax, 0x80000B40
|
||||
out dx, eax
|
||||
mov dx, 0xCFC
|
||||
mov eax, 0x0000B001
|
||||
out dx, eax
|
||||
|
||||
; 3. ACPI Enable
|
||||
mov dx, 0xCF8
|
||||
mov eax, 0x80000B80
|
||||
out dx, eax
|
||||
mov dx, 0xCFC
|
||||
mov eax, 0x00000001
|
||||
out dx, eax
|
||||
|
||||
; 4. Shutdown Command
|
||||
mov dx, 0xB004
|
||||
mov ax, 0x2000
|
||||
out dx, ax
|
||||
|
||||
; 안 꺼지면 대기
|
||||
hlt
|
||||
jmp $
|
||||
|
||||
action_reboot:
|
||||
mov si, msg_reboot
|
||||
call print_serial
|
||||
|
||||
; Reboot Command
|
||||
mov dx, 0x64
|
||||
mov al, 0xFE
|
||||
out dx, al
|
||||
hlt
|
||||
jmp $
|
||||
|
||||
; ===========================================================
|
||||
; [Drivers]
|
||||
; ===========================================================
|
||||
init_serial:
|
||||
mov dx, 0x3FB
|
||||
mov al, 0x80 ; DLAB ON
|
||||
out dx, al
|
||||
mov dx, 0x3F8
|
||||
mov al, 0x0C ; 9600 baud
|
||||
out dx, al
|
||||
mov dx, 0x3F9
|
||||
mov al, 0x00
|
||||
out dx, al
|
||||
mov dx, 0x3FB
|
||||
mov al, 0x03 ; 8N1, DLAB OFF
|
||||
out dx, al
|
||||
ret
|
||||
|
||||
print_serial:
|
||||
mov dx, 0x3F8
|
||||
.loop:
|
||||
lodsb
|
||||
cmp al, 0
|
||||
je .done
|
||||
out dx, al
|
||||
jmp .loop
|
||||
.done:
|
||||
ret
|
||||
|
||||
; ===========================================================
|
||||
; [Data]
|
||||
; ===========================================================
|
||||
; 줄바꿈(0x0D, 0x0A)을 명확히 넣었습니다.
|
||||
msg_boot db 0x0D, 0x0A, "===============================", 0x0D, 0x0A
|
||||
db " SSH Serial BIOS v1.0 ", 0x0D, 0x0A
|
||||
db "===============================", 0x0D, 0x0A, 0
|
||||
|
||||
msg_menu db 0x0D, 0x0A, "COMMANDS: [1] Shutdown [2] Reboot", 0x0D, 0x0A
|
||||
db "Input > ", 0
|
||||
|
||||
msg_bye db 0x0D, 0x0A, ">>> System is HALTING...", 0x0D, 0x0A, 0
|
||||
msg_reboot db 0x0D, 0x0A, ">>> REBOOTING...", 0x0D, 0x0A, 0
|
||||
|
||||
times 65520-($-$$) db 0
|
||||
reset_vector:
|
||||
jmp 0xF000:0x0000
|
||||
times 16-($-reset_vector) db 0
|
||||
@@ -0,0 +1,156 @@
|
||||
; mybios_real.asm
|
||||
[BITS 16]
|
||||
[ORG 0]
|
||||
|
||||
bios_start:
|
||||
; 1. 세그먼트 초기화
|
||||
mov ax, 0xF000
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
xor ax, ax
|
||||
mov ss, ax
|
||||
mov sp, 0x7C00
|
||||
|
||||
; ==========================================================
|
||||
; [VGA BIOS (Option ROM) 실행하기]
|
||||
; QEMU는 0xC0000 번지에 표준 VGA BIOS를 올려둡니다.
|
||||
; 이걸 실행해야 화면이 켜지고 curses가 작동합니다.
|
||||
; ==========================================================
|
||||
|
||||
; 2-1. VGA BIOS가 있는지 확인 (Signature Check)
|
||||
; 0xC000:0000 = 0x55, 0xC000:0001 = 0xAA 여야 함
|
||||
mov ax, 0xC000
|
||||
mov es, ax
|
||||
|
||||
cmp byte [es:0], 0x55
|
||||
jne no_vga
|
||||
cmp byte [es:1], 0xAA
|
||||
jne no_vga
|
||||
|
||||
; 2-2. VGA BIOS 실행 (Far Call)
|
||||
; 보통 3번째 바이트부터 코드가 시작됩니다.
|
||||
; PUSH CS, PUSH IP 방식으로 돌아올 주소를 저장하고 점프합니다.
|
||||
push cs ; 돌아올 세그먼트 (0xF000)
|
||||
push word .vga_ret ; 돌아올 오프셋 (Label 주소)
|
||||
|
||||
; 0xC000:0003 으로 점프!
|
||||
push 0xC000 ; VGA Segment
|
||||
push 0x0003 ; VGA Entry Point
|
||||
retf ; (Far Return을 이용한 점프 기법)
|
||||
|
||||
.vga_ret:
|
||||
; 여기까지 오면 VGA BIOS가 화면을 초기화하고 돌아온 상태입니다!
|
||||
; 이제 다시 우리의 세그먼트 복구
|
||||
mov ax, 0xF000
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
|
||||
; 3. 화면 파란색으로 칠하기 (이제 먹힘!)
|
||||
mov ax, 0xB800
|
||||
mov es, ax
|
||||
|
||||
xor di, di
|
||||
mov cx, 2000
|
||||
mov ax, 0x1F20 ; 파란바탕 + 공백
|
||||
rep stosw
|
||||
|
||||
; 4. 메시지 출력
|
||||
mov si, msg_title
|
||||
mov di, 0
|
||||
call print_vga
|
||||
|
||||
mov si, msg_menu
|
||||
mov di, 160
|
||||
call print_vga
|
||||
|
||||
; 5. 메인 루프 (키보드 0x60)
|
||||
main_loop:
|
||||
in al, 0x64
|
||||
test al, 1
|
||||
jz main_loop
|
||||
|
||||
in al, 0x60
|
||||
|
||||
cmp al, 0x02 ; '1'
|
||||
je action_shutdown
|
||||
cmp al, 0x03 ; '2'
|
||||
je action_reboot
|
||||
jmp main_loop
|
||||
|
||||
; --- 에러 처리: VGA BIOS가 없을 때 ---
|
||||
no_vga:
|
||||
; 시리얼로 에러 메시지라도 보내야 함 (여기선 생략하고 무한루프)
|
||||
cli
|
||||
hlt
|
||||
jmp $
|
||||
|
||||
; ===========================================================
|
||||
; [Actions] (이전과 동일)
|
||||
; ===========================================================
|
||||
action_shutdown:
|
||||
mov si, msg_bye
|
||||
mov di, 320
|
||||
call print_vga
|
||||
|
||||
; ACPI PIIX4 Shutdown
|
||||
mov dx, 0xCF8
|
||||
mov eax, 0x80000B04
|
||||
out dx, eax
|
||||
mov dx, 0xCFC
|
||||
mov eax, 0x0001
|
||||
out dx, eax
|
||||
mov dx, 0xCF8
|
||||
mov eax, 0x80000B40
|
||||
out dx, eax
|
||||
mov dx, 0xCFC
|
||||
mov eax, 0x0000B001
|
||||
out dx, eax
|
||||
mov dx, 0xCF8
|
||||
mov eax, 0x80000B80
|
||||
out dx, eax
|
||||
mov dx, 0xCFC
|
||||
mov eax, 0x00000001
|
||||
out dx, eax
|
||||
mov dx, 0xB004
|
||||
mov ax, 0x2000
|
||||
out dx, ax
|
||||
hlt
|
||||
jmp $
|
||||
|
||||
action_reboot:
|
||||
mov si, msg_reboot
|
||||
mov di, 320
|
||||
call print_vga
|
||||
mov dx, 0x64
|
||||
mov al, 0xFE
|
||||
out dx, al
|
||||
hlt
|
||||
jmp $
|
||||
|
||||
; ===========================================================
|
||||
; [Drivers]
|
||||
; ===========================================================
|
||||
print_vga:
|
||||
mov ah, 0x1F
|
||||
.loop:
|
||||
lodsb
|
||||
cmp al, 0
|
||||
je .done
|
||||
stosw
|
||||
jmp .loop
|
||||
.done:
|
||||
ret
|
||||
|
||||
; ===========================================================
|
||||
; [Data]
|
||||
; ===========================================================
|
||||
msg_title db "=== REAL BIOS (VGA Initialized) ===", 0
|
||||
msg_menu db "Press [1] to Shutdown, [2] to Reboot", 0
|
||||
msg_bye db "System Halted.", 0
|
||||
msg_reboot db "Rebooting...", 0
|
||||
|
||||
; --- BIOS 크기 맞추기 (64KB) ---
|
||||
times 65520-($-$$) db 0
|
||||
reset_vector:
|
||||
jmp 0xF000:0x0000
|
||||
times 16-($-reset_vector) db 0
|
||||
@@ -0,0 +1,123 @@
|
||||
; mybios_boot.asm
|
||||
[BITS 16]
|
||||
[ORG 0x7C00] ; BIOS가 우리를 0x7C00에 로딩해줍니다.
|
||||
|
||||
start:
|
||||
; 1. 세그먼트 초기화
|
||||
xor ax, ax ; AX = 0
|
||||
mov ds, ax ; DS = 0
|
||||
mov es, ax ; ES = 0
|
||||
mov ss, ax ; SS = 0
|
||||
mov sp, 0x7C00 ; 스택 설정
|
||||
|
||||
; 2. 화면 초기화 (블루 스크린)
|
||||
; BIOS가 이미 VGA를 텍스트 모드로 켜둔 상태입니다!
|
||||
; 우리는 메모리에 색칠만 하면 됩니다.
|
||||
mov ax, 0xB800
|
||||
mov es, ax ; ES = 비디오 메모리 세그먼트
|
||||
|
||||
xor di, di ; DI = 0
|
||||
mov cx, 2000 ; 80x25 = 2000 글자
|
||||
mov ax, 0x1F20 ; 파란바탕(1F) + 공백(20)
|
||||
rep stosw ; 화면 지우기
|
||||
|
||||
; 3. 메시지 출력
|
||||
mov si, msg_title
|
||||
mov di, 0
|
||||
call print_vga
|
||||
|
||||
mov si, msg_menu
|
||||
mov di, 160
|
||||
call print_vga
|
||||
|
||||
; 4. 키보드 입력 대기
|
||||
main_loop:
|
||||
in al, 0x64
|
||||
test al, 1
|
||||
jz main_loop
|
||||
|
||||
in al, 0x60 ; 키보드 스캔코드 읽기
|
||||
|
||||
cmp al, 0x02 ; 키 '1'
|
||||
je action_shutdown
|
||||
|
||||
cmp al, 0x03 ; 키 '2'
|
||||
je action_reboot
|
||||
|
||||
jmp main_loop
|
||||
|
||||
; ===========================================================
|
||||
; [Actions]
|
||||
; ===========================================================
|
||||
|
||||
action_shutdown:
|
||||
mov si, msg_bye
|
||||
mov di, 320
|
||||
call print_vga
|
||||
|
||||
; ACPI Shutdown (PIIX4) - 부트로더 상태에서도 똑같이 동작합니다.
|
||||
mov dx, 0xCF8
|
||||
mov eax, 0x80000B04
|
||||
out dx, eax
|
||||
mov dx, 0xCFC
|
||||
mov eax, 0x0001
|
||||
out dx, eax
|
||||
|
||||
mov dx, 0xCF8
|
||||
mov eax, 0x80000B40
|
||||
out dx, eax
|
||||
mov dx, 0xCFC
|
||||
mov eax, 0x0000B001
|
||||
out dx, eax
|
||||
|
||||
mov dx, 0xCF8
|
||||
mov eax, 0x80000B80
|
||||
out dx, eax
|
||||
mov dx, 0xCFC
|
||||
mov eax, 0x00000001
|
||||
out dx, eax
|
||||
|
||||
mov dx, 0xB004
|
||||
mov ax, 0x2000
|
||||
out dx, ax
|
||||
|
||||
hlt
|
||||
jmp $
|
||||
|
||||
action_reboot:
|
||||
mov si, msg_reboot
|
||||
mov di, 320
|
||||
call print_vga
|
||||
|
||||
mov dx, 0x64
|
||||
mov al, 0xFE
|
||||
out dx, al
|
||||
hlt
|
||||
jmp $
|
||||
|
||||
; ===========================================================
|
||||
; [Drivers]
|
||||
; ===========================================================
|
||||
|
||||
print_vga:
|
||||
mov ah, 0x1F ; 파란색 속성 고정
|
||||
.loop:
|
||||
lodsb
|
||||
cmp al, 0
|
||||
je .done
|
||||
stosw
|
||||
jmp .loop
|
||||
.done:
|
||||
ret
|
||||
|
||||
; ===========================================================
|
||||
; [Data]
|
||||
; ===========================================================
|
||||
msg_title db "=== SSH Curses Bootloader (Blue Screen) ===", 0
|
||||
msg_menu db "Press [1] to Shutdown, [2] to Reboot", 0
|
||||
msg_bye db "System Halted.", 0
|
||||
msg_reboot db "Rebooting...", 0
|
||||
|
||||
; --- 부트 섹터 마법 (512바이트 맞추기) ---
|
||||
times 510-($-$$) db 0 ; 510바이트까지 0으로 채움
|
||||
dw 0xAA55 ; 부트 서명 (Boot Signature)
|
||||
@@ -0,0 +1,11 @@
|
||||
# read&write
|
||||
|
||||
```bash
|
||||
nasm -f bin mybios.asm -o mybios.bin
|
||||
qemu-system-i386 -bios mybios.bin -nographic
|
||||
```
|
||||
|
||||
```bash
|
||||
nasm -f bin myboot.asm -o myboot.bin
|
||||
qemu-system-i386 -M pc -drive file=myboot.bin,format=raw,index=0,media=disk -display curses
|
||||
```
|
||||
Reference in New Issue
Block a user