This is the code (I made it as simple as possible, but still feels somehow large):
Code: Select all
PCI_CONFIG_ADDRESS equ 0xCF8
PCI_CONFIG_DATA equ 0xCFC
PCI_BAR_0_OFFSET equ 0x10
PCI_BAR_1_OFFSET equ 0x14
%macro write_pci_register 0
mov dx, PCI_CONFIG_ADDRESS
out dx, eax
mov eax, ebx
mov dx, PCI_CONFIG_DATA
out dx, eax
%endmacro
; PCI_ADDRESS:
; ; Enable Bit Reserved Bus Number Device Number Function Number Register Offset
; ; 31 30 - 24 23 - 16 15 - 11 10 - 8 7 - 0
; QEMU: 1_0000000_00000000_00010_000_00000000b --> 0x8000_1000
; VBOX: 1_0000000_00000000_00110_000_00000000b --> 0x8000_3000
PCI_DEV_ADDRESS equ 0x8000_1000
; BAR_0:
; QEMU: 1111111111111111_1100000000000100
; VBOX: 1111111111111111_0000000000000000
org 0x7C00
bits 16
mov ax, 0x0500 >> 4
mov ss, ax
mov esp, 0x7C00 - 0x0500
mov ax, 0
mov ds, ax
; Disable cache
mov eax, cr0
and eax, 1011_1111_1111_1111__1111_1111_1111_1111b
mov cr0, eax
invd
; Write anything to the MMIO address space
mov ax, 0x1000
mov es, ax
mov byte [es:0x00], 0x7D
; Set MMIO
mov eax, PCI_DEV_ADDRESS | PCI_BAR_0_OFFSET
mov ebx, 0x10000
write_pci_register
mov eax, PCI_DEV_ADDRESS | PCI_BAR_1_OFFSET
mov ebx, 0x00
write_pci_register
; Read the value back
mov ax, 0x1000
mov es, ax
mov byte al, [es:0x00]
; Print anything to screen if the value changed
cmp al, 0x7D
je end
mov ax, 0xB800
mov es, ax
mov word [es:0x00], 0x3300 | 'X'
end:
cli
hlt
jmp end
times 510-($-$$) db 0
dw 0xAA55
These are the commands I use to test with qemu:
Code: Select all
nasm -l kernel.lst kernel.asm ; \
qemu-system-x86_64 \
-device qemu-xhci \
-drive format=raw,file=kernel
Code: Select all
VBoxManage createvm \
--name "X" \
--ostype "Other" \
--register \
--basefolder "$(pwd)/vbox" \
--uuid "e0b08add-d834-4af5-89e8-05abec11aa78" \
--default ; \
VBoxManage modifyvm "e0b08add-d834-4af5-89e8-05abec11aa78" --usbxhci on ; \
nasm -l kernel.lst kernel.asm ; \
dd if=/dev/zero of=kernel.raw bs=1024 count=2048 ; \
dd if=kernel of=kernel.raw conv=notrunc ; \
VBoxManage convertfromraw kernel.raw kernel.vdi --format VDI ; \
VBoxManage storageattach "X" \
--storagectl "IDE" \
--port 0 \
--device 0 \
--type hdd \
--medium "$(pwd)"/kernel.vdi ; \
VBoxManage startvm "X"
VBox version: 6.1.0 r135406
Qemu version: 4.1.0