wok annotate linld/stuff/src/VCPI.ASM @ rev 19905

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