wok view linld/stuff/src/VCPI.ASM @ rev 21143

clamtk: update deps
author Pascal Bellard <pascal.bellard@slitaz.org>
date Wed Mar 27 15:24:38 2019 +0100 (2019-03-27)
parents af959ebf1305
children de6c5f0bf7ea
line source
1 ;***************************************************************
2 ;****** This file is distributed under GPL
3 ;***************************************************************
4 ;VDPI init:
5 ;Call char* prepare_vcpi(void *pagebuf) first to
6 ;initialize paging tables needed for vm86.
7 ;pagebuf needs to be 8k+4 bytes. Returns ptr to 1st unused byte.
8 ;Then call int get_vcpi_interface(). Returns 1 if ok, 0 if bad.
9 ;
10 ;VCPI use:
11 ;u32* malloc_vcpi(u32 size) - source in HIMEM.CPP
12 ; Returns ptr to mallocated zero-terminated list of 4k page addrs
13 ; Addresses are sorted in ascending order
14 ; Never fails (will die if not enough mem)
15 ;void read2vcpi(int fd, u32* vp, u32 size,
16 ;void* xfer_buf, u16 xfer_size) - source in HIMEM.CPP
17 ; Reads opened fd data into malloc_vcpi'ed memory
18 ; Dies if file isn't exactly 'size' bytes long
19 ; Needs intermediate buffer of exactly Nx4k bytes
20 ;void memcpy_vcpi(u32 dstofs,u16 srcseg,u32 srcofs)
21 ; copies 4k from conventional memory to VCPI
22 ;void _vm2rm()
23 ; switches you from vm86 to plain real mode
26 ideal
27 %crefref
28 %noincl
29 %nomacs
30 p386
32 ;****** Stuff for declaring descriptors
33 struc descr
34 limit dw ?
35 base0 dw ?
36 base16 db ?
37 type db ?
38 limit16 db ?
39 base24 db ?
40 ends descr
41 macro descriptor name,typ,plevel,present,limit,gran,base
42 ;;name descr <limit and 0ffffh,base and 0ffffh,low (base shr 16),typ or plevel or present,(limit shr 16) or gran,high (base shr 16)>
43 name descr <limit and 0ffffh,base ,0 ,typ or plevel or present,(limit shr 16) or gran,0 >
44 endm
45 ; decriptor types (bit0..4 of descr.type )
46 tss386_avail = 09h
47 data_seg = 00010000b ; data segment
48 expand_down = 00000100b ; =1 limit counts down from base
49 writable = 00000010b ; =1 if write access allowed to data segment
50 code_seg = 00011000b ; code segment
51 conforming = 00000100b ; =1 code can be accesses and executed at any PL
52 readable = 00000010b ; =1 if code also can be read (cannot be ovwritten)
53 ; privilege levels (bit5..6 of descr.type )
54 priv0 = 00000000b
55 priv1 = 00100000b
56 priv2 = 01000000b
57 priv3 = 01100000b
58 ; segment present bit (bit7 of descr.type )
59 is_present = 10000000b
60 not_present = 00000000b
61 ;definition of granularity ( bits6..7 in descr.limit16 )
62 gran_byte = 00000000b
63 gran_page = 10000000b ; 4k granularity
64 use_16 = 00000000b
65 use_32 = 01000000b
67 ;****** rm32,imm16 helpers
68 macro addzx_e rm,i
69 db 66h
70 add rm,i
71 dw 0
72 endm
75 group DGROUP _TEXT,_BSS
76 assume cs:DGROUP,ds:DGROUP
78 segment _BSS byte public use16 'BSS'
80 tss dd ?,? ;enough, we'll never use it anyway
82 ends _BSS
84 segment _TEXT byte public use16 'CODE'
86 label gdt byte
87 gdt_null descr <?> ;0000
88 gdt_vcpi descr <?> ;0008
89 gdt_vcpi2 descr <?> ;0010
90 gdt_vcpi3 descr <?> ;0018
91 descriptor gdt_abs ,(data_seg+writable),priv0,is_present,0fffffh,(gran_page+use_32),0
92 ;Note: code/data segs must be flagged use16 (i.e. use ip/sp, not eip/esp)
93 ;Note: base addrs will be fixed up in prepare_vcpi()
94 descriptor gdt_code,(code_seg+readable),priv0,is_present,0fffffh,(gran_page+use_16),0
95 global gdt_data:descr
96 descriptor gdt_data,(data_seg+writable),priv0,is_present,0fffffh,(gran_page+use_16),0
97 descriptor gdt_tss ,tss386_avail ,priv0,is_present,0ffh ,gran_byte ,<offset tss>
98 SEL_VCPI = (gdt_vcpi - gdt_null)
99 SEL_TSS = (gdt_tss - gdt_null)
100 SEL_ABS = (gdt_abs - gdt_null)
101 SEL_CODE = (gdt_code - gdt_null)
102 SEL_DATA = (gdt_data - gdt_null)
104 label gdtr pword
105 gdt_lim dw 0ffffh
106 gdt_base dw offset gdt,0
108 ;Note: layout dictated by vcpi api, don't rearrange!
109 label sw2pm_params byte
110 ;Note: base addrs will be fixed up in prepare_vcpi()
111 label pagedir_laddr dword
112 sw2pm_cr3 dd 1000h
113 sw2pm_gdtr_ptr dw offset gdtr,0
114 sw2pm_idtr_ptr dw offset idtr,0
115 sw2pm_ldtr dw 0 ;we don't need it
116 sw2pm_tr dw SEL_TSS ;vcpi thinks we need it... can't set to 0
117 sw2pm_jumpaddr dd 0
118 dw SEL_CODE
120 vcpi_pm_entry dd 0
121 dw SEL_VCPI
123 label idtr pword
124 idt_lim dw 03ffh ;we won't enable ints,
125 idt_base dd 0 ; so let's leave it the same as for rm
128 ;***************************************************************
129 ;char* prepare_vcpi(void *pagebuf);
130 ;****** Return: AX=>first unused byte in pagebuf
131 ;****** Uses: Flags
132 ;***************************************************************
133 global prepare_vcpi:near
134 proc prepare_vcpi near
136 ;pop ax
137 ;pop bx ;pgbuf
138 ;push bx
139 ;push ax
141 ;Calculate pagedir/page0 addrs, initialize cr3 and pagedir[0]
142 xor eax,eax
143 ; heap_top = prepare_vcpi(malloc_or_die(8*1024+4));
144 mov cx,8*1024+4
145 extrn malloc_or_die:near
146 call malloc_or_die ;keep cx
148 mov edx,cs
149 shl edx,cl ;edx = linear addr of CS
150 mov si,offset gdt_vcpi
151 ; Fix up base of some gdt descriptors
152 ; Note: 'add [dword xx.base0],edx' actually updates 24 bit quantity!
153 ; Do NOT replace with mov!
154 mov ebx,10000h-28h
155 add [dword bx+si+sw2pm_idtr_ptr-gdt_vcpi+28h],edx
156 @@fixup:
157 add [dword bx+si+(gdt_code.base0)-gdt_vcpi+28h],edx
158 add bx,8
159 js @@fixup
160 mov bh,10h
161 add eax,edx
162 and ax,0f000h ;eax = 4k aligned linear addr of pagebuf
163 add eax,ebx ;eax=page0 linear addr
164 add [si+sw2pm_cr3-gdt_vcpi],eax
165 mov edi,eax
166 sub edi,edx
167 mov al,3 ;add present+writable bits
168 mov [bx+di],eax ;stuff it into pagedir[0]
169 push ds
170 pop es ;es:di->page0,es:di+1000h->pagedir
171 ;page directory will use only one entry (4 bytes):
172 ;cr3 => pagedir => page0 => ########
173 ; (1 entry) (1024 => # 4M #
174 ; entries)=> # page #
175 ; => ########
176 ; Return
177 lea ax,[bx+di+4]
178 extrn _heap_top:word
179 mov [_heap_top],ax
180 ;ret
182 endp prepare_vcpi
185 ;***************************************************************
186 ;int get_vcpi_interface();
187 ;****** Return: Z - page mapping for low 640k is 1:1
188 ;****** NZ - otherwise (it's bad)
189 ;****** Uses: Flags
190 ;***************************************************************
191 ;global _get_vcpi_interface:near
192 proc _get_vcpi_interface near
194 ;push si di
196 ; Get and save VCPI pm interface
197 ;mov si,offset gdt_vcpi ;DS:DI => 3 GDT entries for VCPI
198 ;mov di,[si+page0_ofs-gdt_vcpi] ;ES:DI => page0
199 ;push ds
200 ;pop es
201 push di
202 mov ax,0DE01h ;get vcpi pm interface
203 int 67h
204 xchg [vcpi_pm_entry],ebx ;clear ebx
205 ;xor bx,bx
207 ; Check that mapping for low 640k is 1:1
208 pop si ; [page0_ofs]
209 ;cld
210 @@map_chk:
211 lodsd
212 shr eax,12
213 cmp ax,bx
214 jne @@bad
215 inc bx
216 cmp al,((640*1024) shr 12)-1
217 jne @@map_chk
218 ; Return
219 @@bad:
220 ret
221 endp _get_vcpi_interface
224 ;***************************************************************
225 ;void memcpy_vcpi(u32 dstofs,u16 srcseg,u32 srcofs);
226 ;***************************************************************
227 ;****** Copies PAGE_SIZE bytes
228 ;****** Uses: Flags
229 ;***************************************************************
230 global vcpi_pm_copy_routine:near
231 proc vcpi_pm_copy_routine near
233 arg dstofs :dword, \
234 srcseg :word, \
235 srcofs :dword = PARAM_SIZE
237 struc pm_regs
238 $$retaddr dw ?
239 $$edi dd ?
240 $$esi dd ?
241 $$ebp dd ?
242 $$esp dd ?
243 $$ebx dd ?
244 $$edx dd ?
245 $$ecx dd ?
246 $$eax dd ?
247 ends
249 ;***************************************************************
250 ;****** Helper: goes into 16bit pm and calls routine (addr on stk)
251 ;***************************************************************
252 mov bp,sp ; ss:bp => struct pm_regs
254 xor ax,ax ; IRET stack for return to vm
255 push ax gs ; (9 dwords)
256 push ax fs ;
257 push ax ds ;
258 push ax es ;
259 push ax ss ;
260 push ebp ; esp
261 pushfd ; eflags: IF saved here
262 push ax cs ;
263 push ax ;\eip
264 push offset @@vm_ret ;/
266 ;;mov [saved_xx],xx ;use if your vcpi trashes bp/etc
268 call switch_to_pm
270 ; Now we are in 16-bit protected mode
271 mov ax,SEL_DATA
272 mov ss,ax
273 ;;mov ds,ax
274 ;;mov es,ax
275 ;;mov fs,ax
276 ;;mov gs,ax
277 assume nothing
278 assume cs:DGROUP
280 ;;mov xx,[saved_xx] ;use if your vcpi trashes bp/etc
281 lea sp,[bp-9*4] ;else we can do this trick with bp
283 ; Call the routine (bp points to params on stack if any)
284 mov bp,[word (pm_regs bp).$$ebp] ;ss:bp => params
285 call do_memcpy_vcpi
287 ; Ok, let's return to vm
288 mov ax,0DE0Ch ; maybe we need whole eax?
289 cli ; to be safe
290 clts ;
291 ;;push SEL_ABS ; vcpi wants ds=all_addrspace
292 ;;pop ds ;
293 call [pword cs:vcpi_pm_entry]
294 @@vm_ret:
295 ; Now we are in vm86 mode. Sregs, esp, eflags (IF) restored from IRET stack
296 ret
298 ;***************************************************************
299 switch_to_pm:
300 assume cs:DGROUP,ds:DGROUP
301 pop [word sw2pm_jumpaddr]
302 ;mov [word sw2pm_jumpaddr+2],0
303 ;mov [word sw2pm_jumpaddr+4],SEL_CODE
304 mov esi,cs
305 shl esi,4
306 addzx_e si,<offset sw2pm_params>
307 mov ax,0DE0Ch ; vcpi: switch to pm
308 cli
309 int 67h
311 ;***************************************************************
312 ;****** Helper: This is where real copy is done
313 ;***************************************************************
314 global do_memcpy_vcpi:near
315 label do_memcpy_vcpi near
317 ; Note: ss:bp => params
318 ; Move data
319 mov al,SEL_ABS
320 mov ds,ax
321 mov es,ax
322 assume nothing
323 assume cs:DGROUP
325 ; Set up target addr:
326 ; replace page mapping for page at 0 so
327 ; that it points to dstofs
328 mov eax,[dstofs]
329 mov al,03h ; writeable, present
330 call @@set_mapping
331 ;push eax ;X we'll need to restore mapping...
332 xor edi,edi ;es:edi => remapped page
334 ; Set up source addr
335 mov esi,[srcofs]
337 ; Do copying
338 xor ecx,ecx
339 mov ch,4096/256
340 ;cld
341 ;; cmp esi,edi
342 ;; jae @@do_copy
343 ;; add esi,ecx ;src<dst: we must do
344 ;; dec esi ; copy backwards to avoid
345 ;; add edi,ecx ; overwrite bug
346 ;; dec edi ;
347 ;; std ;
348 ;;@@do_copy:
349 db 67h ;address width override for esi/edi
350 rep movsb
351 ;; cld
353 ; Restore page mapping for page at 0
354 ;pop eax ;X
355 @@set_mapping:
356 mov esi,[cs:sw2pm_cr3]
357 xchg [esi-1000h],eax ; restore page0[0]
358 mov ecx,cr3 ; reload TLB cache
359 mov cr3,ecx ;
360 ; Return
361 vcpi_ret:
362 ret
364 endp vcpi_pm_copy_routine
365 assume cs:DGROUP,ds:DGROUP
368 ;***************************************************************
369 ;void _vm2rm();
370 ;***************************************************************
371 ;****** Uses: Flags
372 ;***************************************************************
373 global _vm2rm:near
374 proc _vm2rm near
376 ifdef NO386
377 p8086
378 extrn _vcpi:byte
379 test [_vcpi],-1
380 else
381 p386
382 smsw ax ;SMSW cannot be trapped! :-)
383 and al,1 ;MSW_PE
384 endif
385 jz vcpi_ret
386 p386
387 pop ax
388 push cs ;*
389 push ax
390 push si
391 push ds
392 extrn sssp:word
393 mov [sssp],sp
394 ;mov [sssp+2],ss
396 call switch_to_pm
398 ; Now we are in 16-bit protected mode
399 mov ax,SEL_DATA ; load data sregs with limit >=64k
400 mov ss,ax ; or you may get limit violations
401 mov ds,ax ; later in rm
402 ;mov es,ax ; (actually I prefer 4gig limits :-)
403 ;mov fs,ax ;
404 ;mov gs,ax ;
406 ; Black magic here
407 mov eax,cr0
408 and eax,7ffffffeh ; clear PG,P bits
409 mov cr0,eax ; look mommy, we're in rm now!
410 mov cr3,eax ; flush TLB cache
412 ; Now we are in rm, but not yet: have to restore sregs:
413 lss sp,[dword sssp]; SS
414 pop ds ; DS
415 pop si
416 retf ; CS
418 endp _vm2rm
420 ends _TEXT
422 end
424 ;###### END OF FILE ############################################