326 lines
6.5 KiB
NASM
326 lines
6.5 KiB
NASM
; rmmod.asm
|
|
; real mode module for HOS
|
|
; Author: Josh Holtrop
|
|
; Date: 09/20/04
|
|
; Modified: 11/01/05
|
|
|
|
%define VIRT_OFFSET 0xC0000000
|
|
%define SIZEOF_RMPARAMS 20
|
|
%include "rmmod.inc"
|
|
|
|
; the bootstrap process will jump us to 0x0:0x5010 so we'd better be ready for it
|
|
[org 0x5000]
|
|
[bits 32]
|
|
;HOS module header, better be 16 bytes!
|
|
dd 0x4D534F48 ; magic identifier "HOSM"
|
|
dd 1 ; real mode module
|
|
dd start ; start address
|
|
dd 0 ; reserved
|
|
|
|
; ebx = return address
|
|
; ecx = where to store real mode parameter table
|
|
start:
|
|
jmp 24:start_pm16 ; uses KERNEL_CODE_BS16 from kernel/boot.asm
|
|
[bits 16]
|
|
start_pm16: ; in 16-bit protected mode
|
|
mov ax, 32
|
|
mov ss, ax
|
|
mov eax, cr0
|
|
and eax, 0x7FFFFFFE
|
|
mov cr0, eax ; leave PM
|
|
|
|
jmp 0:start_refreshed ; enter RM
|
|
|
|
%include "conio.inc"
|
|
%include "vesa.inc"
|
|
|
|
start_refreshed:
|
|
mov ax, cs ; 0
|
|
mov ds, ax
|
|
mov es, ax
|
|
mov fs, ax
|
|
mov gs, ax
|
|
mov ss, ax
|
|
mov esp, 0x7000
|
|
mov [dat_rmadd], ecx
|
|
mov [dat_retn], ebx
|
|
|
|
mov ebx, ecx ; clear the rm_params
|
|
mov cx, SIZEOF_RMPARAMS
|
|
mov ax, 0
|
|
clear_rmparams_loop:
|
|
mov [ebx], al
|
|
inc ebx
|
|
loop clear_rmparams_loop
|
|
|
|
; begin real-mode code initialization, etc...
|
|
|
|
call con_clear
|
|
|
|
ccall vesa_get_info, es, vbe_info_block
|
|
cmp ax, 0
|
|
jnzfar no_vesa
|
|
|
|
vesa_present:
|
|
ccall con_putstring, txt_vesa
|
|
xor ax, ax
|
|
mov al, [VbeVersion + 1]
|
|
ccall con_putHex, ax
|
|
ccall con_putc, '.' | 0x0700
|
|
xor ax, ax
|
|
mov al, [VbeVersion]
|
|
ccall con_putHex, ax
|
|
ccall con_putc, 10
|
|
|
|
xor ax, ax ; clear the scratch mem
|
|
mov cx, 129
|
|
mov di, scratch_mem
|
|
rep stosw
|
|
|
|
push ds
|
|
mov ax, [OemStringPtr + 2]
|
|
mov si, [OemStringPtr]
|
|
mov ds, ax
|
|
mov di, scratch_mem
|
|
mov cx, 128
|
|
rep movsw ; and copy the string there for display
|
|
pop ds
|
|
|
|
ccall con_putstring, scratch_mem ; write OEM string
|
|
ccall con_putc, 10
|
|
mov ax, [VideoModePtr + 2]
|
|
mov es, ax
|
|
mov si, [VideoModePtr]
|
|
xor dx, dx
|
|
vesa_mode_loop:
|
|
mov ax, [es:si] ; get next mode number
|
|
cmp ax, 0xFFFF
|
|
jzfar vesa_mode_loop_done
|
|
ccall vesa_get_mode_info, ds, vbe_mode_info_block, ax
|
|
cmp ax, 0
|
|
jnzfar vesa_mode_loop_next
|
|
|
|
mov ax, [ModeAttributes]
|
|
and ax, VESA_MODE_SUPPORTED | VESA_MODE_COLOR | VESA_MODE_GRAPHICS | VESA_MODE_LFB
|
|
cmp ax, VESA_MODE_SUPPORTED | VESA_MODE_COLOR | VESA_MODE_GRAPHICS | VESA_MODE_LFB
|
|
jnzfar vesa_mode_loop_next
|
|
mov ax, [XResolution]
|
|
cmp ax, 640
|
|
jlfar vesa_mode_loop_next
|
|
mov ax, [YResolution]
|
|
cmp ax, 480
|
|
jlfar vesa_mode_loop_next
|
|
mov al, [BitsPerPixel]
|
|
cmp al, 15
|
|
jz vesa_mode_good
|
|
cmp al, 16
|
|
jz vesa_mode_good
|
|
cmp al, 24
|
|
jz vesa_mode_good
|
|
cmp al, 32
|
|
jnzfar vesa_mode_loop_next
|
|
vesa_mode_good:
|
|
mov ax, dx
|
|
add ax, 0x0700 | 'a'
|
|
ccall con_putc, ax
|
|
ccall con_putstring, txt_vesa_mode1
|
|
ccall con_putDec, word [XResolution]
|
|
ccall con_putc, 'x' | 0x0700
|
|
ccall con_putDec, word [YResolution]
|
|
ccall con_putc, 'x' | 0x0700
|
|
xor ax, ax
|
|
mov al, [BitsPerPixel]
|
|
ccall con_putDec, ax
|
|
ccall con_putstring, txt_vesa_mode2
|
|
mov ax, [es:si] ; mode number
|
|
ccall con_putHex, ax
|
|
ccall con_putc, 10
|
|
|
|
mov bx, dx
|
|
shl bx, 1
|
|
mov [scratch_mem + bx], ax ; store modes in scratch_mem array
|
|
inc dx
|
|
|
|
vesa_mode_loop_next:
|
|
add si, 2
|
|
jmp vesa_mode_loop
|
|
|
|
vesa_mode_loop_done:
|
|
ccall con_putstring, txt_vesa_end
|
|
|
|
vesa_get_key_loop:
|
|
call con_getkey
|
|
mov ah, 0
|
|
cmp ax, '0'
|
|
jz vesa_the_end
|
|
cmp ax, 'a' ; first choice
|
|
jb vesa_get_key_loop
|
|
add dx, 'a'
|
|
cmp ax, dx ; one past last choice
|
|
jae vesa_get_key_loop
|
|
; ok, we have a valid video mode selection
|
|
sub ax, 'a'
|
|
shl ax, 1
|
|
mov bx, ax
|
|
mov cx, [scratch_mem + bx]
|
|
ccall vesa_get_mode_info, ds, vbe_mode_info_block, cx
|
|
or cx, 0x4000 ; enable LFB
|
|
ccall vesa_set_mode, cx ; turn on mode
|
|
|
|
mov ebx, [dat_rmadd] ; pass mode info to kernel
|
|
mov eax, [PhysBasePtr]
|
|
mov [ebx + 0], eax
|
|
xor eax, eax
|
|
mov al, [BitsPerPixel]
|
|
mov [ebx + 12], eax
|
|
mov ax, [XResolution]
|
|
mov [ebx + 4], eax
|
|
mov ax, [YResolution]
|
|
mov [ebx + 8], eax
|
|
|
|
jmp vesa_the_end
|
|
|
|
|
|
|
|
no_vesa:
|
|
ccall con_putstring, txt_novesa
|
|
call con_getkey
|
|
|
|
vesa_the_end:
|
|
|
|
end_rmmod: ; get ready to go back to pmode and return to kernel initialization
|
|
mov ebx, [dat_retn]
|
|
lgdt [gdtrlin32]
|
|
mov eax, cr0
|
|
or eax, 0x01
|
|
mov cr0, eax
|
|
jmp KERNEL_CODE_LIN32:segmented_start
|
|
|
|
[bits 32]
|
|
segmented_start:
|
|
lgdt [gdtrbs32]
|
|
jmp KERNEL_CODE_BS32:offset_continue+VIRT_OFFSET
|
|
offset_continue:
|
|
mov cx, KERNEL_DATA_BS32
|
|
mov ss, cx
|
|
mov ds, cx
|
|
mov es, cx
|
|
mov gs, cx
|
|
mov fs, cx
|
|
jmp ebx
|
|
|
|
|
|
[bits 16]
|
|
|
|
;-------------------------------------------------------
|
|
gdtrlin32:
|
|
dw gdt_endlin32-gdtlin32-1
|
|
dd gdtlin32
|
|
gdtlin32: ;null descriptor
|
|
dd 0
|
|
dd 0
|
|
|
|
KERNEL_CODE_LIN32 equ $-gdtlin32
|
|
db 0xff ;limit 7:0
|
|
db 0xff ;limit 15:8
|
|
db 0x00 ;base 7:0
|
|
db 0x00 ;base 15:8
|
|
db 0x00 ;base 23:16
|
|
db 0x9a ;access
|
|
db 0xcf ;flags / limit 19:16
|
|
db 0x00 ;base 31:24
|
|
|
|
KERNEL_DATA_LIN32 equ $-gdtlin32
|
|
db 0xff ;limit 7:0
|
|
db 0xff ;limit 15:8
|
|
db 0x00 ;base 7:0
|
|
db 0x00 ;base 15:8
|
|
db 0x00 ;base 23:16
|
|
db 0x92 ;access
|
|
db 0xcf ;flags / limit 19:16
|
|
db 0x00 ;base 31:24
|
|
|
|
gdt_endlin32:
|
|
|
|
|
|
;-------------------------------------------------------
|
|
gdtrbs32:
|
|
dw gdt_endbs32-gdtbs32-1
|
|
dd gdtbs32
|
|
gdtbs32: ;null descriptor
|
|
dd 0
|
|
dd 0
|
|
|
|
;a base of 0x4000_0000, when added to 0xC000_0000 will produce 0x0000_0000 physical before paging in effect
|
|
KERNEL_CODE_BS32 equ $-gdtbs32
|
|
db 0xff ;limit 7:0
|
|
db 0xff ;limit 15:8
|
|
db 0x00 ;base 7:0
|
|
db 0x00 ;base 15:8
|
|
db 0x00 ;base 23:16
|
|
db 0x9a ;access
|
|
db 0xcf ;flags / limit 19:16
|
|
db 0x40 ;base 31:24
|
|
|
|
KERNEL_DATA_BS32 equ $-gdtbs32
|
|
db 0xff ;limit 7:0
|
|
db 0xff ;limit 15:8
|
|
db 0x00 ;base 7:0
|
|
db 0x00 ;base 15:8
|
|
db 0x00 ;base 23:16
|
|
db 0x92 ;access
|
|
db 0xcf ;flags / limit 19:16
|
|
db 0x40 ;base 31:24
|
|
|
|
gdt_endbs32:
|
|
|
|
|
|
txt_vesa: db "VESA found. VBE Version: ", 0
|
|
txt_vesa_mode1 db ". ", 0
|
|
txt_vesa_mode2 db ", mode 0x", 0
|
|
txt_vesa_end: db "Enter the letter of your selection or 0 for console mode:", 0
|
|
txt_novesa: db "VESA not found, using 80x25 console mode... press any key", 10, 0
|
|
|
|
dat_rmadd: dd 0
|
|
dat_retn: dd 0
|
|
|
|
vbe_info_block:
|
|
VbeSignature: db "VBE2"
|
|
VbeVersion: dw 0
|
|
OemStringPtr dd 0
|
|
Capabilities: times 4 db 0
|
|
VideoModePtr: dd 0
|
|
TotalMemory: dw 0
|
|
OemSoftwareRev: dw 0
|
|
OemVendorName: dd 0
|
|
OemProductName: dd 0
|
|
OemProductRev: dd 0
|
|
Reserved: times 478 db 0
|
|
|
|
vbe_mode_info_block:
|
|
ModeAttributes: dw 0
|
|
WinAAttributes: db 0
|
|
WinBAttributes: db 0
|
|
WinGranularity: dw 0
|
|
WinSize: dw 0
|
|
WinASegment: dw 0
|
|
WinBSegment: dw 0
|
|
WinFuncPtr: dd 0
|
|
BytesPerScanline: dw 0
|
|
|
|
XResolution: dw 0
|
|
YResolution: dw 0
|
|
XCharSize: db 0
|
|
YCharSize: db 0
|
|
NumberOfPlanes: db 0
|
|
BitsPerPixel: db 0
|
|
NumberOfBanks: db 0
|
|
MemoryModel: db 0
|
|
BankSize: db 0
|
|
NumberOfImagePages: db 0
|
|
Reserved2: times 10 db 0
|
|
PhysBasePtr: dd 0
|
|
Reserved3: times 212 db 0
|
|
|
|
scratch_mem:
|