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

linld: add quick boot switch (again)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Fri Feb 19 18:33:17 2021 +0000 (2021-02-19)
parents bc4b94310a29
children 61df94a0fa43
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 %PAGESIZE 1000
28 %crefref
29 %noincl
30 %nomacs
31 p386
33 ;****** Stuff for declaring descriptors
34 struc descr
35 limit dw ?
36 base0 dw ?
37 base16 db ?
38 type db ?
39 limit16 db ?
40 base24 db ?
41 ends descr
42 macro descriptor name,typ,plevel,present,limit,gran,base
43 ;;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)>
44 name descr <limit and 0ffffh,base ,0 ,typ or plevel or present,(limit shr 16) or gran,0 >
45 endm
46 ; decriptor types (bit0..4 of descr.type )
47 tss386_avail = 09h
48 data_seg = 00010000b ; data segment
49 expand_down = 00000100b ; =1 limit counts down from base
50 writable = 00000010b ; =1 if write access allowed to data segment
51 code_seg = 00011000b ; code segment
52 conforming = 00000100b ; =1 code can be accesses and executed at any PL
53 readable = 00000010b ; =1 if code also can be read (cannot be ovwritten)
54 ; privilege levels (bit5..6 of descr.type )
55 priv0 = 00000000b
56 priv1 = 00100000b
57 priv2 = 01000000b
58 priv3 = 01100000b
59 ; segment present bit (bit7 of descr.type )
60 is_present = 10000000b
61 not_present = 00000000b
62 ;definition of granularity ( bits6..7 in descr.limit16 )
63 gran_byte = 00000000b
64 gran_page = 10000000b ; 4k granularity
65 use_16 = 00000000b
66 use_32 = 01000000b
68 ;****** rm32,imm16 helper
69 macro movzx_e rm,i
70 db 66h
71 mov rm,i
72 dw 0
73 endm
75 macro pushd sreg
76 db 66h
77 push sreg
78 endm
80 group DGROUP _TEXT
81 assume cs:DGROUP,ds:DGROUP
83 segment _TEXT byte public use16 'CODE'
85 ;***************************************************************
86 ;int get_vcpi_interface();
87 ;****** Return: Z - page mapping for low 640k is 1:1
88 ;****** NZ - otherwise (it's bad)
89 ;****** Uses: Flags
90 ;***************************************************************
91 ;global _get_vcpi_interface:near
92 proc _get_vcpi_interface near
94 ;push si di
96 ; Get and save VCPI pm interface
97 ;mov si,offset gdt_vcpi ;DS:DI => 3 GDT entries for VCPI
98 ;mov di,[si+page0_ofs-gdt_vcpi] ;ES:DI => page0
99 ;push ds
100 ;pop es
101 ;push di
102 ;mov ax,0DE01h ;get vcpi pm interface
103 int 67h
104 xchg [si+vcpi_pm_entry-gdt_vcpi],ebx ; bx=((640*1024) shr 12)
106 ; Check that mapping for low 640k is 1:1
107 pop si ; [page0_ofs]
108 ;cld
109 mov cx,bx
110 @@map_chk:
111 lodsd
112 shr eax,12
113 add ax,cx
114 ;cmp eax,ebx ; ((640*1024) shr 12)
115 cmp ax,bx ; ((640*1024) shr 12)
116 loope @@map_chk
117 ;pop di si
118 ret
120 endp _get_vcpi_interface
123 ;***************************************************************
124 ;char* prepare_vcpi(void *pagebuf);
125 ;****** Return: AX=>first unused byte in pagebuf
126 ;****** Uses: Flags
127 ;***************************************************************
128 global prepare_vcpi:near
129 proc prepare_vcpi near
131 ;Calculate pagedir/page0 addrs, initialize cr3 and pagedir[0]
132 ; heap_top = prepare_vcpi(malloc_or_die(8*1024+4));
134 ;mov edx,cs
135 ;shl edx,4 ;edx = linear addr of CS
136 mov si,offset gdt_vcpi
137 ; Fix up base of some gdt descriptors
138 ; Note: 'add [dword xx.base0],edx' actually updates 24 bit quantity!
139 ; Do NOT replace with mov!
140 mov bx,10000h-28h
141 add [dword si+sw2pm_addr-gdt_vcpi],edx
142 add [dword si+sw2pm_idtr_ptr-gdt_vcpi],edx
143 @@fixup:
144 add [dword bx+si+(gdt_code.base0)-gdt_vcpi+28h],edx
145 add bx,8
146 js @@fixup
147 mov bh,10h
148 extrn _heap_top:word
149 ;movzx eax,[_heap_top]
150 mov ax,[_heap_top]
151 add ax,bx ; assume _heap_top < 0f000h
152 add eax,edx
153 and ax,0f000h ;eax = 4k aligned linear addr of pagebuf
154 add [si+sw2pm_cr3-gdt_vcpi],eax ;eax=page0 linear addr
155 mov edi,eax
156 sub edi,edx
157 mov al,3 ;add present+writable bits
158 mov [bx+di],eax ;stuff it into pagedir[0]
159 push ds
160 pop es ;es:di->page0,es:di+1000h->pagedir
161 ;page directory will use only one entry (4 bytes):
162 ;cr3 => pagedir => page0 => ########
163 ; (1 entry) (1024 => # 4M #
164 ; entries)=> # page #
165 ; => ########
166 ; Return
167 lea ax,[bx+di+4]
168 mov [_heap_top],ax
169 ;ret
170 push di
171 mov ax,0DE01h ;get vcpi pm interface
172 jmp _get_vcpi_interface
174 endp prepare_vcpi
176 org $-40
177 tss dd ?,? ;enough, we'll never use it anyway
178 label gdt byte
179 gdt_null descr <?> ;0000
180 gdt_vcpi descr <?> ;0008
181 gdt_vcpi2 descr <?> ;0010
182 gdt_vcpi3 descr <?> ;0018
183 org $-8
184 global gdt_memcpy:descr
185 gdt_memcpy descr <?> ;null + gdt_abs
186 descriptor gdt_abs ,(data_seg+writable),priv0,is_present,0fffffh,(gran_page+use_32),0
187 ;Note: code/data segs must be flagged use16 (i.e. use ip/sp, not eip/esp)
188 ;Note: base addrs will be fixed up in prepare_vcpi()
189 descriptor gdt_code,(code_seg+readable),priv0,is_present,0fffffh,(gran_page+use_16),0
190 global gdt_data:descr
191 descriptor gdt_data,(data_seg+writable),priv0,is_present,0fffffh,(gran_page+use_16),0
192 descriptor gdt_tss ,tss386_avail ,priv0,is_present,0ffh ,gran_byte ,<offset tss>
193 SEL_VCPI = (gdt_vcpi - gdt_null)
194 SEL_TSS = (gdt_tss - gdt_null)
195 SEL_ABS = (gdt_abs - gdt_null)
196 SEL_CODE = (gdt_code - gdt_null)
197 SEL_DATA = (gdt_data - gdt_null)
199 label gdtr pword
200 gdt_lim dw 0ffffh
201 gdt_base dw offset gdt,0
203 ;Note: layout dictated by vcpi api, don't rearrange!
204 label sw2pm_params byte
205 ;Note: base addrs will be fixed up in prepare_vcpi()
206 label pagedir_laddr dword
207 sw2pm_cr3 dd 1000h
208 sw2pm_gdtr_ptr dw offset gdtr,0
209 sw2pm_idtr_ptr dw offset idtr,0
210 sw2pm_ldtr dw 0 ;we don't need it
211 sw2pm_tr dw SEL_TSS ;vcpi thinks we need it... can't set to 0
212 sw2pm_jumpaddr dw offset pmode,0
213 dw SEL_CODE
215 vcpi_pm_entry dd ((640*1024) shr 12)
216 dw SEL_VCPI
218 label idtr pword
219 idt_lim dw 03ffh ;we won't enable ints,
220 idt_base dd 0 ; so let's leave it the same as for rm
223 ;***************************************************************
224 ;void memcpy_vcpi(u32 dstofs,u16 srcseg,u32 srcofs);
225 ;***************************************************************
226 ;****** Copies PAGE_SIZE bytes
227 ;****** Uses: Flags
228 ;***************************************************************
229 global vcpi_pm_copy_routine:near
230 proc vcpi_pm_copy_routine near
232 struc pm_regs
233 $$retaddr dw ?
234 $$edi dd ?
235 $$esi dd ?
236 $$ebp dd ?
237 $$esp dd ?
238 $$ebx dd ?
239 $$edx dd ?
240 $$ecx dd ?
241 $$eax dd ?
242 ends
244 ;***************************************************************
245 ;****** Helper: goes into 16bit pm and calls routine (addr on stk)
246 ;***************************************************************
247 mov bp,sp ; ss:bp => struct pm_regs
249 mov bx,5 ; IRET stack for return to vm
250 @@push_sreg:
251 pushd ss ; fake pushd gs fs ds es ss
252 dec bx
253 jnz @@push_sreg ; (9 dwords)
254 push ebp ; esp
255 pushfd ; eflags: IF saved here
256 pushd cs ;
257 push bx ;\eip
258 push offset vcpi_ret ;/
260 mov edx,esi
261 switch_to_pm:
262 movzx_e si,<offset sw2pm_params>
263 org $-4
264 sw2pm_addr dd ?
265 mov ax,0DE0Ch ; vcpi: switch to pm
266 cli ; load GDTR LDTR TR need 16 bytes in SS:ESP
267 int 67h ; EAX, ESI, DS, ES, FS, GS destroyed
268 pmode:
269 assume nothing
270 assume cs:DGROUP
272 ; Now we are in 16-bit protected mode
273 push SEL_DATA
274 pop ss
275 test bx,bx
276 jnz vm2rm_end
278 ;lea sp,[bp-8-9*4]
279 lea sp,[bp-9*4]
281 ; Call the routine (bp points to params on stack if any)
282 call do_memcpy_vcpi ; set ds=all_addrspace
284 ; Ok, let's return to vm
285 mov ax,0DE0Ch ; maybe we need whole eax?
286 cli ; to be safe
287 clts ;
288 ; Go to vm86 mode. Sregs, esp, eflags (IF) restored from IRET stack
289 call [pword cs:vcpi_pm_entry]
290 ret
291 ;jmp [pword cs:vcpi_pm_entry]
293 ;***************************************************************
295 ;***************************************************************
296 ;****** Helper: This is where real copy is done
297 ;***************************************************************
298 label do_memcpy_vcpi near
300 push SEL_ABS
301 pop ds
302 push ds
303 pop es
304 assume nothing
305 assume cs:DGROUP
307 ; Set up target addr:
308 ; replace page mapping for page at 0 so
309 ; that it points to dstofs
310 xchg eax,edi
311 mov al,03h ; writeable, present
312 call @@set_mapping
313 xor edi,edi ;es:edi => remapped page
315 ; Set up source addr
316 mov esi,edx
318 ; Do copying
319 db 67h ;address width override for esi/edi
320 rep movsb
322 @@set_mapping:
323 mov esi,[cs:sw2pm_cr3]
324 xchg [esi-1000h],eax ; restore page0[0]
325 mov esi,cr3 ; reload TLB cache
326 mov cr3,esi ;
327 ; Return
328 vcpi_ret:
329 ret
331 endp vcpi_pm_copy_routine
334 ;***************************************************************
335 ;void _vm2rm();
336 ;***************************************************************
337 ;****** Uses: Flags
338 ;***************************************************************
339 global _vm2rm:far
340 proc _vm2rm far
342 assume cs:DGROUP,ds:DGROUP
343 push ds
344 extrn sssp:dword
345 mov bx,offset sssp
346 mov [bx],sp
347 ;mov [bx+2],ss
348 ifdef QUICK_BOOT
349 extrn _cmdnum:dword
350 v86boot = (byte _cmdnum+24)
351 test [v86boot],bh
352 jnz @vm2rm_ret
353 endif
354 ifdef NO386
355 extrn _vcpi:byte
356 test [_vcpi],bh
357 else
358 smsw ax ;SMSW cannot be trapped! :-)
359 and al,1 ;MSW_PE
360 endif
361 jz @vm2rm_ret
362 jmp switch_to_pm ; EAX, ESI, DS, ES, FS, GS destroyed
363 vm2rm_end:
364 assume nothing
365 assume cs:DGROUP
367 ;push ss
368 ;pop ds
370 ; Now we are in 16-bit protected mode
371 ; Black magic here
372 mov eax,cr0
373 and eax,7ffffffeh ; clear PG,P bits
374 mov cr0,eax ; look mommy, we're in rm now!
375 mov cr3,eax ; flush TLB cache
377 ; Now we are in rm, but not yet: have to restore sregs:
378 lss sp,[cs:bx] ; SS
379 @vm2rm_ret:
380 pop ds ; DS
381 retf ; CS
383 endp _vm2rm
385 ends _TEXT
387 end
389 ;###### END OF FILE ############################################