NASM - The Netwide Assembler

NASM Forum => Programming with NASM => Topic started by: Deskman243 on April 11, 2023, 05:03:20 PM

Title: How can I return from protected mode to make BIOS calls again
Post by: Deskman243 on April 11, 2023, 05:03:20 PM
From earlier posts on the forum I was trying to test code between privilege levels so I had designed a small label for a gate in protected mode to try and reset the values by the GDT accordingly. Instead I made another segment for my code to go through the steps when I realized that my boot code couldn't make calls from the new real mode.Originally I was making a task state segment value and was happy that all the other functions worked in the section until I called from the IDT pipeline to truly verify the state between protected modes. Here is the source for this code.

Code: [Select]

%define BUILD_GDT_DESC(bounds,base,access,flags) \
((( base & 0x00FFFFFF) << 16) | \
(( base & 0xFF000000) << 32) | \
( bounds & 0x0000FFFF) | \
(( bounds & 0x000F0000) << 32) | \
(( access & 0xFF) << 40) | \
(( flags & 0x0F) << 52))

TSS_IO_MAP_SIZE EQU 0x400/8

[BITS 16]

section .data

ROWS EQU 25
COLS1 EQU 80

section .text

_prep_module2:
jmp _prep_module2_

Idtpipe32:
dw 0
dd 0



_prep_module2_:
cld
cli

in al,0x92
or al,2
out 0x92,al

; mov [saved_segment],ds

lgdt[gdt32Ptr]
lidt[Idtpipe32]

mov word [gate_voucher],GATE_VOUCHER

protectedGate:
mov eax,cr0
or eax,1
mov cr0,eax

jmp code32_post:protectedMode

;.pm_track:
; mov word [gate_voucher],GATE_CHECK
; jmp protectedGate

[bits 32]
trail:
jmp $
; mov sp,bp
; ret

protectedMode:
mov cx,word [gate_voucher]
cmp cx,0
jz trail

mov dword [saved_segment],data32_post
call task_prod

; mov ebp,tss32_post
; ltr bp

call task_poke

mov esp,edx
mov esp,PM_MODE_STACK

mov ah,COLOR_ATTR_PSC
mov al,ah
mov esi, pm_str

call printstr_pm

; jmp $

prep_stage:
mov ebp,tss

mov edx,0
mov ecx,0
; mov ebp,0
.prep_loop1:
mov es:bp,dx
add bp,1
cmp bp,0x8298
; cmp bp,0x8319
jnz .prep_loop1

; jmp prototype2

.prep_stage2:
mov word [tss.iomap_base],tss.iomap - tss
mov ebp,tss32_post
ltr bp

_prep_stage1:
; lgdt[gdt16Ptr]
jmp rm_poll_function
; jmp 0:rm_poll_function

;[bits 16]
;use16
;testing states
rm_poll_function:
;use16
cli
xor ecx,ecx
mov ebp,esp

;rmGate:
; jmp 0:rm_poll_state
; jmp cs:rm_poll_state

; use16
; jmp rmGate
; jmp 0:rmGate
jmp code16_post:rmGate


[bits 16]
rm_trail:
ret


rmGate:

mov ecx,data16_post
mov es,cx
; mov cs,cx
mov ds,cx
mov fs,cx
mov gs,cx
mov ss,cx

mov eax,cr0
mov [save_cr0],eax
and eax,07ffffffeh
mov cr0,eax


; lgdt[gdt32Ptr]
; lidt[Idtpipe]

; mov word [gate_voucher],GATE_VOUCHER
; push word [gate_voucher]
; pop cx
mov cx,1

cmp cx,0
jz rm_trail

; jmp code16_post:rm_poll_state
jmp 0:rm_poll_state

; push cs
; push rm_poll_state
; retf
Idtpipe:
dw 0x3ff
dd 0

Idtpipe2:
dw 0xffff
dd 0

rm_poll_state:



xor eax,eax
xor ecx,ecx

; mov sp,0x0000_9000
mov esp,0x00009000
; mov sp,0x9000


; mov cx,0
mov es,cx
; mov cs,cx
mov ss,cx
mov ds,cx
mov fs,cx
mov gs,cx
; mov sp,0x0000_9000
lidt[Idtpipe2]
sti


jmp retstack
; jmp prototype

mov dword [saved_segment],data16_post
mov word [gate_voucher],GATE_CHECK

call task_prod16
; call task_poke16
call poll_function1

call color_function
; jmp retstack
; jmp prototype

; jmp protectedGate2
; jmp protectedGate.pm_track
jmp _prep_module3

; jmp $

retstack:
; pushf
push 0x0000
; push byte data16_post
; push byte code16_post
; push byte Idtpipe
push word color_function
retf
; retfw

prototype:
xor ax,ax
mov ds,ax
mov ax,[0x40]
mov dx,[0x42]
mov [pre],ax
mov [pre+2],dx
mov word [0x40],handler
mov [0x42],cs
mov ah,0x0e
mov al,'h'
int 0x10
jmp $

handler:
inc ax
jmp far [pre]
pre: dd 0

poll_function1:
.prep:

xor ebx,ebx
xor edx,edx

; mov ax,0
mov cx,0
mov es,cx
mov ax,ROWS
mov bx,es:0x044A
mul bx
add ax,COLS1
shl ax,1
mov si,ax

; mov cx,0B000H
; test byte es:0x0410,2
; jnz .Address_OK
mov cx,0B800H

.Address_OK:
mov es,cx
mov al,'H'

mov es:[si],byte al
; mov es:0,byte al
mov es:si,byte al
mov ds:si,byte al
mov ds:[si],byte al
inc si
ret
; jmp $

loopcheck:
; hlt
jmp loopcheck


color_function:
  ; set base pointer to heap
  ; and stack pointer to stack for functions and variables
mov dx,sp

  mov ax,0x13
  int 0x10
 
mov cx,0xA000
mov es,cx

mov word[X],50
mov word[Y],60
call color_method

mov word[X],100
mov word[Y],60
  call color_method

mov word[X],120
mov word[Y],120
  call color_method
mov word[X],140
mov word[Y],30
  call color_method
mov sp,dx
; hlt
ret
color_method :
  mov ax, word[X]
  mov bx, word[Y]
  xor si, si
add si,word 320
  imul si, bx
  add si, ax
  mov cx, word[color_pkg]
  mov [es:si], cx
 
  ret



task_poke16:

; mov word [gate_voucher],1
;check wizard stall
mov cx,word [gate_voucher]
cmp cx,0
jnz .prep

.prep:
mov eax,[tss.eax]
mov ecx,[tss.ecx]
mov edx,[tss.edx]
mov ebx,[tss.ebx]
mov esp,[tss.esp]
mov ebp,[tss.ebp]
mov esi,[tss.esi]
mov edi,[tss.type2]

mov cx,[tss.ds]
mov es,cx
; mov cs,cx
mov ss,cx
mov ds,cx
mov fs,cx
mov gs,cx

mov cx,word [gate_voucher]
cmp cx,0
jnz .post

; call rmGate

.post:
ret

;%endif

;[bits 32]
task_prod16:
mov cx,word [gate_voucher]
cmp cx,0
jnz .inst_placer
; call protectedGate
.reference:
mov word [tss.ecx],cx
mov word [tss.esp1],sp
mov cx,ss
mov word [tss.ss1],cx

.inst_placer:
pop cx
push cx

mov word [tss.eip],cx
.prep:
; pushd ecx
pushf
; popf dword [tss.eflags]
pop cx
mov word [tss.eflags],cx


mov word [tss.eax],ax
; mov dword [tss.ecx],ecx
mov word [tss.edx],dx
mov word [tss.ebx],bx
mov word [tss.esp],sp
mov word [tss.ebp],bp
mov word [tss.esi],si
mov word [tss.type2],di

push cx
mov cx,[saved_segment]
mov word [tss.es],cx
mov word [tss.cs],cx
mov word [tss.ss],cx
mov word [tss.ds],cx
mov word [tss.fs],cx
mov word [tss.gs],cx

pop cx

ret
;r2pm_backtrack:

_prep_module3:
cld
cli

in al,0x92
or al,2
out 0x92,al

; mov [saved_segment],ds

lgdt[gdt32Ptr]
lidt[Idtpipe32]

mov word [gate_voucher],GATE_VOUCHER

protectedGate2:
mov eax,cr0
or eax,1
mov cr0,eax

jmp code32_post:modeProtect2

;.pm_track:
; mov word [gate_voucher],GATE_CHECK
; jmp protectedGate

[bits 32]
trail2:
jmp $
; mov sp,bp
; ret

modeProtect2:
mov word [saved_segment],data32_post

; call task_poke
mov ecx,[saved_segment]
mov es,cx
; mov cs,cx
mov ss,cx
mov ds,cx
mov fs,cx
mov gs,cx

.loopcheck:
jmp $

printstr_pm:
push ds
; push esi
push eax
; push ebp
mov ebp,0
jmp .gettext
.output:
mov esi,[vidmem_ptr]
add esi,ebp
mov [es:esi],ax
add ebp,2
pop esi
.gettext:
mov al,[ds:si]
add si,1
push esi
test al,al
jnz .output
.stub1:
dec esi
shr ebp,1
add esi,ebp
mov [vidmem_ptr],esi
pop esi
pop eax
pop ds
ret


task_poke:
mov cx,word [gate_voucher]
cmp cx,0
jnz .prep
.prep:
mov eax,[tss.eax]
mov ecx,[tss.ecx]
mov edx,[tss.edx]
mov ebx,[tss.ebx]
mov esp,[tss.esp]
mov ebp,[tss.ebp]
mov esi,[tss.esi]
mov edi,[tss.type2]

mov cx,[tss.ds]
mov es,cx
; mov cs,cx
mov ss,cx
mov ds,cx
mov fs,cx
mov gs,cx

mov cx,word [gate_voucher]
cmp cx,0
jnz .post

; call rmGate

.post:
ret


;%endif

;[bits 32]
task_prod:
mov cx,word [gate_voucher]
cmp cx,0
jnz .inst_placer


mov dword [tss.ecx],ecx
.inst_placer:
pop ecx
push ecx

mov dword [tss.eip],ecx
.prep:
; pushd ecx
pushf
; popf dword [tss.eflags]
pop ecx
mov dword [tss.eflags],ecx


mov dword [tss.eax],eax
; mov dword [tss.ecx],ecx
mov dword [tss.edx],edx
mov dword [tss.ebx],ebx
mov dword [tss.esp],esp
mov dword [tss.ebp],ebp
mov dword [tss.esi],esi
mov dword [tss.type2],edi

push ecx
mov cx,[saved_segment]
mov word [tss.es],cx
mov word [tss.cs],cx
mov word [tss.ss],cx
mov word [tss.ds],cx
mov word [tss.fs],cx
mov word [tss.gs],cx

pop ecx

ret

section .rodata
  __STACK__ dd 0x00FFFFFF
  __HEAP__ dd 0x00008C24

  VGA_MEM dw 0xA000
  WIDTH dw 320
  HEIGHT dw 219
 

VIDEO_TEXT_ADDR EQU 0XB8000
COLOR_ATTR_PSC EQU 0X6A
COLOR_ATTR_BSC EQU 0X5F
PM_MODE_STACK EQU 0X80000
VM_STACK_SEG EQU 0X0000
VM_STACK_OFS EQU 0X0000
VM_CS_SEG EQU 0X0000
FLAGS_VM_CMP EQU 17
FLAGS_CMP1 EQU 1
FLAGS_CMP_IF EQU 9
FLAGS_CMP_IOPL EQU 12
RING0_PROC_STACK_SIZE EQU 2048
;TSS_IO_MAP_SIZE EQU 0
TSS_IO_MAP_SIZE EQU 0x400/8
;VM_STACK_ADDRESS EQU vidmem_address
GATE_CHECK EQU 0
GATE_VOUCHER EQU 1


section .data

align 4
gdt32:
dq BUILD_GDT_DESC(0,0,0,0)
gdt32code:
dq BUILD_GDT_DESC(0x0000ffff,0,10011010b,1100b)
gdt32data:
dq BUILD_GDT_DESC(0x0000ffff,0,10010010b,1100b)
gdt16code:
dq BUILD_GDT_DESC(0x0000ffff,0,10011010b,1000b)
gdt16data:
dq BUILD_GDT_DESC(0x0000ffff,0,10010010b,1000b)

;gdt16tss:dq BUILD_GDT_DESC(0x8230,TSS_SIZE-1,10001001b,0000b) & 0 << 22
gdt32tss:
dq BUILD_GDT_DESC(TSS_SIZE-1,0x8470,10001001b,0000b)
; dq BUILD_GDT_DESC(TSS_SIZE-1,0x9260,10001001b,0000b)
.stub1:

code32_post: equ gdt32code -gdt32
data32_post: equ gdt32data -gdt32
;.stub:
code16_post: equ gdt16code -gdt32
data16_post: equ gdt16data -gdt32

tss32_post: equ gdt32tss -gdt32

gdt32Len: equ $-gdt32
gdt32Ptr: dw gdt32Len-1
dd gdt32


;align 4
vidmem_ptr: dd VIDEO_TEXT_ADDR
pm_str: db 'protected mode string ',0
pm_str_length: equ $-pm_str
vm_str: db 'virtual',0
;vidmem_address: dw 0

;resb 512
times 512 db 0

align 16
tss:
.back_link: dd 0
.esp0: dd 0
.ss0: dd 0
.esp1: dd 0
.ss1: dd 0
.esp2: dd 0
.ss2: dd 0
.cr3: dd 0
.eip: dd 0
.eflags: dd 0
.eax: dd 0
.ecx: dd 0
.edx: dd 0
.ebx: dd 0
.esp: dd 0
.ebp: dd 0
.esi: dd 0
.type2: dd 0
.es: dd 0
.cs: dd 0
.ss: dd 0
.ds: dd 0
.fs: dd 0
.gs: dd 0
.ldt: dd 0
.trap: dw 0
.iomap_base: dw 0

.iomap: TIMES TSS_IO_MAP_SIZE db 0x00

%if TSS_IO_MAP_SIZE > 0
.iomap_pad:db 0xff

%endif
.end:
TSS_SIZE: EQU tss.end -tss

save_cr0 dd 0
saved_segment resd 0
gate_voucher dw 1

X dd 0
Y   dd 0
color_pkg dw 5



What I essentially was doing was combining all the steps that I could use to walkthrough the 16 <-->32 gates.Right now what I understand is
0) Makefile settings for debugging elf i386 objects
1) GDT references for size 16&32
2) Code settings for cr0 between 16&32
3) Long jumps to reset state values (like from the sources online)
4) Distinct models for 16&32 size tasks
5) Returns values from most other mode functions
6) New protected mode gate restate
Testing code.
7) IDT reference calls
8) retf stack method resets
9) other sources

So hopefully one of the good chat users could show us how to go about this because the answer would check out a good amount of methods.
Cheers!
Title: Re: How can I return from protected mode to make BIOS calls again
Post by: Deskman243 on April 11, 2023, 06:17:38 PM
For similarly related subjects you can check out my response on the other recent post in the forum on this link
https://forum.nasm.us/index.php?topic=3668.0

Also I posted the newer version of this on this link here
https://stackoverflow.com/questions/76011742/proof-of-concept-for-16-to-32-protected-mode-bios-taskings