APM Protected Mode Interface
Posted: Sun Apr 27, 2008 9:41 am
Hi,
reading the the APM 1.2 specification I found out that there ist a function to initialisize a protected mode interface for APM.
And here a the three GDT entries I'll fillup later with values:
Now, let's fill them:
Now the documentation tell me how to use the APM protected mode interface:
It doesn't work, but I don't know why. As my assembler I'm using NASM.
Thank for every help I can get.
reading the the APM 1.2 specification I found out that there ist a function to initialisize a protected mode interface for APM.
So I called this function in the real mode part of my kernel and stored the returns of this function in some variables:4.6.4 APM Protected Mode 32-bit Interface Connect (03H)
This call initializes the 32-bit protected mode interface between the APM Driver
(caller) and the APM BIOS. This interface allows a protected mode APM Driver to
invoke the APM BIOS functions without the need to first switch into real or virtual-86
mode. This function must be invoked in real mode.
Call With
AH = 53H APM
AL = 03H Protected mode 32-bit interface connect
BX = Power device ID
0000H APM BIOS
All other values are reserved
Returns
If function successful:
Carry = 0
AX = PM 32-bit code segment (real mode segment base address)
EBX = Offset of the entry point into the APM BIOS
CX = APM 16-bit code segment (real mode segment base address)
DX = APM data segment (real mode segment base address)
ESI = APM BIOS 32-bit code segment length (low word of ESI)
APM BIOS 16-bit code
segment length (high word of ESI)
DI = APM BIOS data segment length
If function unsuccessful:
Carry = 1
AH = Error code
02H Real mode interface connection already established
05H 16-bit protected mode interface connection already
established
07H 32-bit protected mode interface connection already
established
08H 32-bit protected mode interface not supported
09H Unrecognized device ID
86H APM not present
Code: Select all
mov ah, 0x53
mov al, 0x03
mov bx, 0x00
int 15h
jne next_twelve
mov si, kernelE_msg
call print
mov byte [apm_pm], 0x01
mov word [apm_32_code_segment], ax
mov dword [apm_offset_entry_point], ebx
mov word [apm_16_code_segment], cx
mov word [apm_data_segment], dx
mov word [apm_32_code_length], si
mov word [apm_16_code_length], esi
mov word [apm_data_length], di
Code: Select all
APM_32_CODE_SEL equ $-gdt
gdt6:
dw 0xFFFF ; Limit wird zur Laufzeit eingetragen
dw 0 ; (base gets set above)
db 0
db 0x92 ; present, ring 0, data, expand-up, writable
db 0 ; page-granular, 16-bit
db 0
APM_16_CODE_SEL equ $-gdt
gdt7:
dw 0xFFFF
dw 0 ; (base gets set above)
db 0
db 0x92 ; present, ring 0, data, expand-up, writable
db 0 ; byte-granular, 16-bit
db 0
APM_DATA_SEL equ $-gdt
gdt8:
dw 0xFFFF ; Limit wird zu Laufzeit eingetragen
dw 0 ; (base gets set above)
db 0
db 0x92 ; present, ring 0, data, expand-up, writable
db 0 ; page-granular, 16-bit
db 0
Code: Select all
; Write segment length
mov word dx, [apm_32_code_length]
sub dx, 0x01
mov word [gdt6], dx
mov word ax, [apm_16_code_length]
sub dx, 0x01
mov word [gdt7], dx
mov word ax, [apm_data_length]
sub dx, 0x01
mov word [gdt8], dx
;Write segment base address
mov word dx, [apm_32_code_segment]
mov word [gdt6 + 2], dx
mov word dx, [apm_16_code_segment]
mov word [gdt7 + 2], dx
mov word dx, [apm_data_segment]
mov word [gdt8 + 2], dx
I've tried this one directly out of my kernel:The APM BIOS 32-bit protected mode interface requires 3 consecutive
selector/segment descriptors for use as 32-bit code, 16-bit code, and data segments,
respectively. Both 32-bit and 16-bit code segment descriptors are necessary so the
APM BIOS 32-bit interface can call other BIOS routines in a 16-bit code segment if
necessary. The caller must initialize these descriptors using the segment base and
length information returned from this call to the APM BIOS. These selectors may
either be in the GDT or LDT, but must be valid when the APM BIOS is called in
protected mode. The code segment descriptors must specify protection level 0, and
the APM BIOS routines must be invoked with CPL = 0 so they can execute privileged
instructions such as port inputs and outputs.
The three segment lengths returned in DI and the high/low words of ESI must contain
the lengths of their respective segments in bytes. The protected mode segment
descriptors created for these segments will have a limit that is 1 less than the length.
For example, a segment with length 0800H will be given a segment limit of 07FFH,
allowing access to offsets 0 to 07FFH within the segment.
The APM caller invokes the APM BIOS routines using the 32-bit interface by making
a far call to the 32-bit code segment selector it initializes, with the offset returned in
EBX from this call. The caller must supply a stack large enough for use by the APM
BIOS and potential interrupt handlers. The caller's stack will be active if or when
interrupts are enabled in the APM BIOS routines; the BIOS will not switch stacks
when interrupts are enabled, including NMI interrupts. The APM BIOS 32-bit
protected mode interface must be called with a 32-bit stack.
When the APM BIOS routines are called in protected mode, the current I/O
permission bit map must allow access to the I/O ports the BIOS may need to access in
the process of performing the selected function.
Code: Select all
mov ax, 0x28
mov ds, ax
mov ax,530eh
xor bx,bx
mov cx,0102h
call [ds:edi]
mov ax,530fh
mov bx,0001h
mov cx,0001h
call [ds:edi]
mov ax,5308h
mov bx,0001h
mov cx,0001h
call [ds:edi]
mov ax,5307h
mov bx,0001h
mov cx,0003h
call [ds:edi]
Thank for every help I can get.