rename: study -> qemu
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
; mybios.asm
|
||||
[BITS 16]
|
||||
[ORG 0]
|
||||
|
||||
bios_start:
|
||||
; 1. 세그먼트 초기화 (CS=0xF000 이므로 DS, ES도 맞춤)
|
||||
mov ax, 0xF000
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
|
||||
; mov ss, ax
|
||||
; mov sp, 0xFFF0
|
||||
xor ax, ax ; AX = 0
|
||||
mov ss, ax ; SS = 0x0000 (RAM)
|
||||
mov sp, 0xFFFE ; 0x0000 ~ 0xFFFF 영역 중 가장 끝!
|
||||
; mov sp, 0x7C00 ; SP = 0x7C00 (부트로더가 쓰는 안전한 RAM 공간)
|
||||
|
||||
; 2. 시리얼 포트(COM1) 초기화 (필수!)
|
||||
mov dx, 0x3FB ; Line Control Register
|
||||
mov al, 0x80 ; DLAB bit set
|
||||
out dx, al
|
||||
|
||||
mov dx, 0x3F8 ; Divisor (Low) - 9600 baud
|
||||
mov al, 0x0C
|
||||
out dx, al
|
||||
|
||||
mov dx, 0x3F9 ; Divisor (High)
|
||||
mov al, 0x00
|
||||
out dx, al
|
||||
|
||||
mov dx, 0x3FB ; LCR: 8 bits, no parity, 1 stop bit
|
||||
mov al, 0x03
|
||||
out dx, al
|
||||
|
||||
; 3. 메시지 출력
|
||||
mov si, msg_bios
|
||||
call print_serial
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; ===========================================================
|
||||
; [ACPI Shutdown Sequence for QEMU PIIX4 Chipset]
|
||||
; Target: Bus 0, Device 1, Function 3 (Power Management)
|
||||
; Address Format: 1(En) | Bus(0) | Dev(1) | Func(3) | Reg
|
||||
; Hex Prefix: 0x80 | 00 | 08 | 03 | ..
|
||||
; Combined: 0x80000B.. (Function 3 is the key)
|
||||
; ===========================================================
|
||||
|
||||
; Step 0: Enable I/O Access (Command Register - 0x04)
|
||||
; We must tell the chipset to allow I/O port access first.
|
||||
mov dx, 0xCF8
|
||||
mov eax, 0x80000B04 ; Address: Func 3, Reg 0x04
|
||||
out dx, eax
|
||||
|
||||
mov dx, 0xCFC
|
||||
mov eax, 0x0001 ; Value: Bit 0 (I/O Space Enable)
|
||||
out dx, eax
|
||||
|
||||
; Step 1: Set ACPI Base Address (PMBA - 0x40)
|
||||
; We map the ACPI registers to I/O port 0xB000.
|
||||
mov dx, 0xCF8
|
||||
mov eax, 0x80000B40 ; Address: Func 3, Reg 0x40
|
||||
out dx, eax
|
||||
|
||||
mov dx, 0xCFC
|
||||
mov eax, 0x0000B001 ; Value: Base 0xB000 | Bit 0 (Hardwired to 1)
|
||||
out dx, eax
|
||||
|
||||
; Step 2: Enable ACPI Function (PMREGMISC - 0x80)
|
||||
mov dx, 0xCF8
|
||||
mov eax, 0x80000B80 ; Address: Func 3, Reg 0x80
|
||||
out dx, eax
|
||||
|
||||
mov dx, 0xCFC
|
||||
mov eax, 0x00000001 ; Value: Bit 0 (ACPI Enable)
|
||||
out dx, eax
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
mov si, msg_off
|
||||
call print_serial
|
||||
|
||||
; ; Exit with return value 0
|
||||
mov dx, 0xB004
|
||||
mov ax, 0x2000 ; SLP_TYP(Soft Off) | SLP_EN
|
||||
out dx, ax
|
||||
|
||||
; ; reboot
|
||||
; mov dx, 0x64
|
||||
; mov al, 0xFE
|
||||
; out dx, al
|
||||
|
||||
; ; exit (isa-debug-exit; need '-device isa-debug-exit,iobase=0x501,iosize=0x04')
|
||||
; mov dx, 0x501
|
||||
; mov al, 0x02 ; exit code (2) -> qemu exits with exit code (al<<1)|1
|
||||
; out dx, al
|
||||
|
||||
; 그래도 안 꺼지면 그냥 멈춰라
|
||||
cli
|
||||
hlt
|
||||
jmp $
|
||||
|
||||
; --- 시리얼 출력 함수 ---
|
||||
print_serial:
|
||||
mov dx, 0x3F8 ; COM1 데이터 포트
|
||||
.loop:
|
||||
lodsb ; [DS:SI] -> AL
|
||||
cmp al, 0
|
||||
je .done
|
||||
out dx, al ; 한 글자 전송
|
||||
jmp .loop
|
||||
.done:
|
||||
ret
|
||||
|
||||
; msg_bios db "Hello! This is a CUSTOM BIOS running on QEMU!", 0x0D, 0x0A, 0
|
||||
msg_bios db "Hello! This is a CUSTOM BIOS running on QEMU!", 0x0D, 0x0A, 0
|
||||
msg_off db "ACPI Enabled. Powering Off NOW!", 0x0D, 0x0A, 0
|
||||
|
||||
|
||||
; Padding
|
||||
times 65520-($-$$) db 0
|
||||
|
||||
reset_vector:
|
||||
jmp 0xF000:0x0000
|
||||
times 16-($-reset_vector) db 0
|
||||
Reference in New Issue
Block a user