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