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