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

Add openct
author Pascal Bellard <pascal.bellard@slitaz.org>
date Mon Apr 03 15:12:17 2017 +0200 (2017-04-03)
parents 38eb1fe036b4
children 2bd6324d64bf
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,_DATA,_BSS
76 assume cs:DGROUP,ds:DGROUP
78 segment _DATA byte public use16 'DATA'
80 label gdt byte
81 gdt_null descr <?> ;0000
82 gdt_vcpi descr <?> ;0008
83 gdt_vcpi2 descr <?> ;0010
84 gdt_vcpi3 descr <?> ;0018
85 descriptor gdt_abs ,(data_seg+writable),priv0,is_present,0fffffh,(gran_page+use_32),0
86 ;Note: code/data segs must be flagged use16 (i.e. use ip/sp, not eip/esp)
87 ;Note: base addrs will be fixed up in prepare_vcpi()
88 descriptor gdt_code,(code_seg+readable),priv0,is_present,0fffffh,(gran_page+use_16),0
89 descriptor gdt_data,(data_seg+writable),priv0,is_present,0fffffh,(gran_page+use_16),0
90 descriptor gdt_tss ,tss386_avail ,priv0,is_present,0ffh ,gran_byte ,<offset tss>
91 SEL_VCPI = (gdt_vcpi - gdt_null)
92 SEL_TSS = (gdt_tss - gdt_null)
93 SEL_ABS = (gdt_abs - gdt_null)
94 SEL_CODE = (gdt_code - gdt_null)
95 SEL_DATA = (gdt_data - gdt_null)
97 label gdtr pword
98 gdt_lim dw 0ffffh
99 gdt_base dw offset gdt,0
101 ;Note: layout dictated by vcpi api, don't rearrange!
102 label sw2pm_params byte
103 ;Note: base addrs will be fixed up in prepare_vcpi()
104 label pagedir_laddr dword
105 sw2pm_cr3 dd ?
106 sw2pm_gdtr_ptr dw offset gdtr,0
107 sw2pm_idtr_ptr dw offset idtr,0
108 sw2pm_ldtr dw 0 ;we don't need it
109 sw2pm_tr dw SEL_TSS ;vcpi thinks we need it... can't set to 0
110 sw2pm_jumpaddr dd 0
111 dw SEL_CODE
113 vcpi_pm_entry dd 0
114 dw SEL_VCPI
116 label idtr pword
117 idt_lim dw 03ffh ;we won't enable ints,
118 idt_base dd 0 ; so let's leave it the same as for rm
120 ends _DATA
122 segment _BSS byte public use16 'BSS'
124 ;Pagedir/page0 addrs: linear, seg:0 and cs:ofs
125 page0_laddr dd ?
126 ;pagedir_ofs dw ?
127 ;page0_ofs dw ?
129 label saved_ss_sp dword
130 saved_sp dw ?
131 saved_ss dw ?
133 tss dd ?,? ;enough, we'll never use it anyway
135 ends _BSS
137 segment _TEXT byte public use16 'CODE'
139 ;***************************************************************
140 ;char* prepare_vcpi(void *pagebuf);
141 ;****** Return: AX=>first unused byte in pagebuf
142 ;****** Uses: Flags
143 ;***************************************************************
144 global _prepare_vcpi:near
145 global prepare_vcpi:near
146 proc _prepare_vcpi near
148 ;pop ax
149 ;pop bx ;pgbuf
150 ;push bx
151 ;push ax
152 prepare_vcpi:
153 ;push esi
154 ;push es
156 ;Calculate pagedir/page0 addrs, initialize cr3 and pagedir[0]
157 xor eax,eax
158 ; heap_top = prepare_vcpi(malloc_or_die(8*1024+4));
159 mov cx,8*1024+4
160 extrn malloc_or_die:near
161 call malloc_or_die
163 mov cl,4
164 mov edx,cs
165 shl edx,cl ;edx = linear addr of CS
166 mov si,offset gdt_vcpi
167 ; Fix up base of some gdt descriptors
168 ; Note: 'add [dword xx.base0],edx' actually updates 24 bit quantity!
169 ; Do NOT replace with mov!
170 xor ebx,ebx
171 add [dword bx+si+sw2pm_idtr_ptr-gdt_vcpi],edx
172 @@fixup:
173 add [dword bx+si+(gdt_code.base0)-gdt_vcpi],edx
174 add bl,8
175 cmp bl,28h
176 jb @@fixup
177 ;add [dword si+(gdt_data.base0)-gdt_vcpi],edx
178 ;add [dword si+(gdt_tss.base0)-gdt_vcpi],edx
179 ;add [dword si+gdt_base-gdt_vcpi],edx
180 ;add [dword si+sw2pm_gdtr_ptr-gdt_vcpi],edx
181 ;add [dword si+sw2pm_idtr_ptr-gdt_vcpi],edx
182 add eax,edx
183 mov bx,0FFFh
184 add eax,ebx
185 inc bx ;ebx=00001000h
187 shr eax,cl
188 mov al,0 ;eax = 4k aligned linear addr of pagebuf
189 mov es,ax ;es:0->page0,es:1000h->pagedir
190 shl eax,cl ;eax=page0 linear addr
191 mov al,3 ;add present+writable bits
192 mov [es:bx],eax ;stuff it into pagedir[0]
193 push ds
194 pop es
196 mov al,0
197 mov [page0_laddr],eax
198 add eax,ebx
199 ;mov [pagedir_laddr],eax
200 ;page directory will use only one entry (4 bytes):
201 ;cr3 => pagedir => page0 => ########
202 ; (1 entry) (1024 => # 4M #
203 ; entries)=> # page #
204 ; => ########
205 mov [sw2pm_cr3],eax
206 sub eax,edx ;ax = offset in CS of pagedir
207 ;mov [pagedir_ofs],ax
208 sub ax,bx ;ax-=1000
209 ;mov [page0_ofs],ax
210 mov di,ax ;ES:DI => page0
211 ; Return
212 ;pop es
213 ;pop esi
214 add ax,1004h
215 extrn _heap_top:word
216 mov [_heap_top],ax
217 ;ret
219 endp _prepare_vcpi
222 ;***************************************************************
223 ;int get_vcpi_interface();
224 ;****** Return: Z - page mapping for low 640k is 1:1
225 ;****** NZ - otherwise (it's bad)
226 ;****** Uses: Flags
227 ;***************************************************************
228 global _get_vcpi_interface:near
229 proc _get_vcpi_interface near
231 ;push si di
233 ; Get and save VCPI pm interface
234 ;mov si,offset gdt_vcpi ;DS:DI => 3 GDT entries for VCPI
235 ;mov di,[si+page0_ofs-gdt_vcpi] ;ES:DI => page0
236 ;push ds
237 ;pop es
238 push di
239 mov ax,0DE01h ;get vcpi pm interface
240 int 67h
241 xchg [vcpi_pm_entry],ebx ;clear ebx
242 ;xor bx,bx
244 ; Check that mapping for low 640k is 1:1
245 pop si ; [page0_ofs]
246 ;cld
247 @@map_chk:
248 lodsd
249 shr eax,12
250 cmp ax,bx
251 jne @@bad
252 inc bx
253 cmp al,((640*1024) shr 12)-1
254 jne @@map_chk
255 ; Return
256 @@bad:
257 ret
258 endp _get_vcpi_interface
261 ;***************************************************************
262 ;void memcpy_vcpi(u32 dstofs,u16 srcseg,u32 srcofs);
263 ;***************************************************************
264 ;****** Copies PAGE_SIZE bytes
265 ;****** Uses: Flags
266 ;***************************************************************
267 global call_pm_routine:near
268 proc call_pm_routine near
270 arg dstofs :dword, \
271 srcseg :word, \
272 srcofs :dword = PARAM_SIZE
274 struc pm_regs
275 $$retaddr dw ?
276 $$f dw ?
277 $$edi dd ?
278 $$esi dd ?
279 $$ebp dd ?
280 $$esp dd ?
281 $$ebx dd ?
282 $$edx dd ?
283 $$ecx dd ?
284 $$eax dd ?
285 ends
287 ;***************************************************************
288 ;****** Helper: goes into 16bit pm and calls routine (addr on stk)
289 ;***************************************************************
290 mov bp,sp ; ss:bp => struct pm_regs
292 xor ax,ax ; IRET stack for return to vm
293 push ax gs ; (9 dwords)
294 push ax fs ;
295 push ax ds ;
296 push ax es ;
297 push ax ss ;
298 push ebp ; esp
299 pushfd ; eflags: IF saved here
300 push ax cs ;
301 push ax ;\eip
302 push offset @@vm_ret ;/
304 ;;mov [saved_xx],xx ;use if your vcpi trashes bp/etc
306 call switch_to_pm
308 ; Now we are in 16-bit protected mode
309 mov ax,SEL_DATA
310 mov ss,ax
311 ;;mov ds,ax
312 ;;mov es,ax
313 ;;mov fs,ax
314 ;;mov gs,ax
315 assume nothing
316 assume cs:DGROUP
318 ;;mov xx,[saved_xx] ;use if your vcpi trashes bp/etc
319 lea sp,[bp-9*4] ;else we can do this trick with bp
321 ; Call the routine (bp points to params on stack if any)
322 mov ax,[(pm_regs bp).$$f] ; ss:bp => struct pm_regs
323 mov bp,[word (pm_regs bp).$$ebp] ;ss:bp => params
324 call ax
326 ; Ok, let's return to vm
327 mov ax,0DE0Ch ; maybe we need whole eax?
328 cli ; to be safe
329 clts ;
330 push SEL_ABS ; vcpi wants ds=all_addrspace
331 pop ds ;
332 call [pword cs:vcpi_pm_entry]
333 @@vm_ret:
334 ; Now we are in vm86 mode. Sregs, esp, eflags (IF) restored from IRET stack
335 ret
337 ;***************************************************************
338 switch_to_pm:
339 assume cs:DGROUP,ds:DGROUP
340 pop [word sw2pm_jumpaddr]
341 ;mov [word sw2pm_jumpaddr+2],0
342 ;mov [word sw2pm_jumpaddr+4],SEL_CODE
343 mov esi,cs
344 shl esi,4
345 addzx_e si,<offset sw2pm_params>
346 mov ax,0DE0Ch ; vcpi: switch to pm
347 cli
348 int 67h
350 ;***************************************************************
351 ;****** Helper: This is where real copy is done
352 ;***************************************************************
353 global do_memcpy_vcpi:near
354 label do_memcpy_vcpi near
356 ; Note: ss:bp => params
357 ; Move data
358 mov ax,SEL_ABS
359 mov ds,ax
360 mov es,ax
361 assume nothing
362 assume cs:DGROUP
364 ; Set up target addr:
365 ; replace page mapping for page at 0 so
366 ; that it points to dstofs
367 mov eax,[dstofs]
368 mov al,03h ; writeable, present
369 call @@set_mapping
370 ;push eax ;X we'll need to restore mapping...
371 xor edi,edi ;es:edi => remapped page
373 ; Set up source addr
374 mov esi,[srcofs]
376 ; Do copying
377 xor ecx,ecx
378 mov ch,4096/256
379 ;cld
380 ;; cmp esi,edi
381 ;; jae @@do_copy
382 ;; add esi,ecx ;src<dst: we must do
383 ;; dec esi ; copy backwards to avoid
384 ;; add edi,ecx ; overwrite bug
385 ;; dec edi ;
386 ;; std ;
387 ;;@@do_copy:
388 db 67h ;address width override for esi/edi
389 rep movsb
390 ;; cld
392 ; Restore page mapping for page at 0
393 ;pop eax ;X
394 @@set_mapping:
395 mov esi,[cs:page0_laddr]
396 xchg [esi],eax ; restore page0[0]
397 mov ecx,cr3 ; reload TLB cache
398 mov cr3,ecx ;
399 ; Return
400 ret
402 endp call_pm_routine
403 assume cs:DGROUP,ds:DGROUP
406 ;***************************************************************
407 ;void _vm2rm();
408 ;***************************************************************
409 ;****** Uses: Flags
410 ;***************************************************************
411 global _vm2rm:near
412 proc _vm2rm near
414 p8086
415 extrn _vcpi:byte
416 test [_vcpi],-1
417 jz @@ret
418 p386
419 push si
420 ;;pushf
421 ;;pushad
422 push cs ;*
423 push ds
424 ;push es
425 mov [saved_ss],ss
426 mov [saved_sp],sp
428 call switch_to_pm
430 ; Now we are in 16-bit protected mode
431 mov ax,SEL_DATA ; load data sregs with limit >=64k
432 mov ss,ax ; or you may get limit violations
433 mov ds,ax ; later in rm
434 ;mov es,ax ; (actually I prefer 4gig limits :-)
435 ;mov fs,ax ;
436 ;mov gs,ax ;
438 ; Black magic here
439 mov eax,cr0
440 and eax,7ffffffeh ; clear PG,P bits
441 mov cr0,eax ; look mommy, we're in rm now!
442 ;;jmp short $+2
443 ;;xor eax,eax
444 mov cr3,eax ; flush TLB cache
446 ; Now we are in rm, but not yet: have to restore sregs:
447 lss sp,[saved_ss_sp]; SS
448 ;pop es ; ES
449 pop ds ; DS
450 ;push cs ;* done earlier
451 push offset @@next
452 retf ; CS
453 @@next:
454 ;;popad
455 ;;popf
456 pop si
457 @@ret:
458 ret ; We don't care much about rest (FS/GS)
460 endp _vm2rm
462 ends _TEXT
464 end
466 ;###### END OF FILE ############################################