Subversion Repositories Kolibri OS

Rev

Rev 1992 | Rev 2100 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 2089 $
  9.  
  10.  
  11. DRV_COMPAT   equ  5  ;minimal required drivers version
  12. DRV_CURRENT  equ  6  ;current drivers model version
  13.  
  14. DRV_VERSION equ (DRV_COMPAT shl 16) or DRV_CURRENT
  15. PID_KERNEL  equ 1    ;os_idle thread
  16.  
  17. align 4
  18. proc attach_int_handler stdcall, irq:dword, handler:dword, access_rights:dword
  19.  
  20.          pushfd
  21.          cli
  22.  
  23.          push ebx
  24.  
  25.          mov  ebx, [irq]                   ;irq num
  26.          test ebx, ebx
  27.          jz   .err
  28.          cmp  ebx, 15                      ; hidnplayr says: we only have 16 IRQ's
  29.          ja   .err
  30.          mov  eax, [handler]
  31.          test eax, eax
  32.          jz   .err
  33.  
  34.          mov  [irq_tab+ebx*4], eax
  35.          stdcall enable_irq, [irq]
  36.          pop ebx
  37.          mov eax, 1
  38.          popfd
  39.          ret
  40. .err:
  41.          pop ebx
  42.          xor eax, eax
  43.          popfd
  44.          ret
  45. endp
  46.  
  47. proc get_int_handler stdcall, irq:dword
  48.  
  49.         mov     eax, [irq]
  50.  
  51.         mov     eax, [irq_tab + 4 * eax]
  52.         ret
  53. endp
  54.  
  55. align 4
  56. proc  detach_int_handler
  57.  
  58.            ret
  59. endp
  60.  
  61. align 4
  62. proc enable_irq stdcall, irq_line:dword
  63.            mov ebx, [irq_line]
  64.            mov edx, 0x21
  65.            cmp ebx, 8
  66.            jb @F
  67.            mov edx, 0xA1
  68.            sub ebx,8
  69. @@:
  70.            in al,dx
  71.            btr eax, ebx
  72.            out dx, al
  73.            ret
  74. endp
  75.  
  76. align 16
  77. ;; proc irq_serv
  78.  
  79. irq_serv:
  80.  
  81. .irq_1:
  82.            push 1
  83.            jmp .main
  84. align 4
  85. .irq_2:
  86.            push 2
  87.            jmp .main
  88. align 4
  89. .irq_3:
  90.            push 3
  91.            jmp .main
  92. align 4
  93. .irq_4:
  94.            push 4
  95.            jmp .main
  96. align 4
  97. .irq_5:
  98.            push 5
  99.            jmp .main
  100. align 4
  101. .irq_6:
  102.            push 6
  103.            jmp .main
  104. align 4
  105. .irq_7:
  106.            push 7
  107.            jmp .main
  108. align 4
  109. .irq_8:
  110.            push 8
  111.            jmp .main
  112. align 4
  113. .irq_9:
  114.            push 9
  115.            jmp .main
  116. align 4
  117. .irq_10:
  118.            push 10
  119.            jmp .main
  120. align 4
  121. .irq_11:
  122.            push 11
  123.            jmp .main
  124. align 4
  125. .irq_12:
  126.            push 12
  127.            jmp .main
  128. ; align 4
  129. ; .irq_13:
  130. ;          push 13
  131. ;          jmp .main
  132. align 4
  133. .irq_14:
  134.            push 14
  135.            jmp .main
  136. align 4
  137. .irq_15:
  138.            push 15
  139.            jmp .main
  140.  
  141. align 16
  142. .main:
  143.            save_ring3_context
  144.            mov   eax, [esp + 32]
  145.            mov   bx, app_data  ;os_data
  146.            mov   ds, bx
  147.            mov   es, bx
  148.  
  149.            cmp   [v86_irqhooks+eax*8], 0
  150.            jnz   v86_irq
  151.  
  152.            cmp   al, 6
  153.            jnz   @f
  154.            push  eax
  155.            call  [fdc_irq_func]
  156.            pop   eax
  157. @@:
  158.  
  159.            cmp   al, 14
  160.            jnz   @f
  161.            push  eax
  162.            call  [irq14_func]
  163.            pop   eax
  164. @@:
  165.            cmp   al, 15
  166.            jnz   @f
  167.            push  eax
  168.            call  [irq15_func]
  169.            pop   eax
  170. @@:
  171.  
  172.            mov ebx, [irq_tab+eax*4]
  173.            test ebx, ebx
  174.            jz .exit
  175.  
  176.            call ebx
  177.            mov  [check_idle_semaphore],5
  178.  
  179. .exit:
  180.  
  181.        cmp dword [esp + 32], 8
  182.            mov al, 0x20
  183.            jb @f
  184.        out 0xa0, al
  185. @@:
  186.            out 0x20, al
  187.  
  188.            restore_ring3_context
  189.            add   esp, 4
  190.  
  191.            iret
  192.  
  193. align 4
  194. proc get_notify stdcall, p_ev:dword
  195.  
  196. .wait:
  197.            mov ebx,[current_slot]
  198.            test dword [ebx+APPDATA.event_mask],EVENT_NOTIFY
  199.            jz @f
  200.            and dword [ebx+APPDATA.event_mask], not EVENT_NOTIFY
  201.            mov edi, [p_ev]
  202.            mov dword [edi], EV_INTR
  203.            mov eax, [ebx+APPDATA.event]
  204.            mov dword [edi+4], eax
  205.            ret
  206. @@:
  207.            call change_task
  208.            jmp .wait
  209. endp
  210.  
  211. align 4
  212. proc pci_read32 stdcall, bus:dword, devfn:dword, reg:dword
  213.            push ebx
  214.            xor eax, eax
  215.            xor ebx, ebx
  216.            mov ah, byte [bus]
  217.            mov al, 6
  218.            mov bh, byte [devfn]
  219.            mov bl, byte [reg]
  220.            call pci_read_reg
  221.            pop ebx
  222.            ret
  223. endp
  224.  
  225. align 4
  226. proc pci_read16 stdcall, bus:dword, devfn:dword, reg:dword
  227.            push ebx
  228.            xor eax, eax
  229.            xor ebx, ebx
  230.            mov ah, byte [bus]
  231.            mov al, 5
  232.            mov bh, byte [devfn]
  233.            mov bl, byte [reg]
  234.            call pci_read_reg
  235.            pop ebx
  236.            ret
  237. endp
  238.  
  239. align 4
  240. proc pci_read8 stdcall, bus:dword, devfn:dword, reg:dword
  241.            push ebx
  242.            xor eax, eax
  243.            xor ebx, ebx
  244.            mov ah, byte [bus]
  245.            mov al, 4
  246.            mov bh, byte [devfn]
  247.            mov bl, byte [reg]
  248.            call pci_read_reg
  249.            pop ebx
  250.            ret
  251. endp
  252.  
  253. align 4
  254. proc pci_write8 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
  255.            push ebx
  256.            xor eax, eax
  257.            xor ebx, ebx
  258.            mov ah, byte [bus]
  259.            mov al, 8
  260.            mov bh, byte [devfn]
  261.            mov bl, byte [reg]
  262.            mov ecx, [val]
  263.            call pci_write_reg
  264.            pop ebx
  265.            ret
  266. endp
  267.  
  268. align 4
  269. proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
  270.            push ebx
  271.            xor eax, eax
  272.            xor ebx, ebx
  273.            mov ah, byte [bus]
  274.            mov al, 9
  275.            mov bh, byte [devfn]
  276.            mov bl, byte [reg]
  277.            mov ecx, [val]
  278.            call pci_write_reg
  279.            pop ebx
  280.            ret
  281. endp
  282.  
  283. align 4
  284. proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword
  285.            push ebx
  286.            xor eax, eax
  287.            xor ebx, ebx
  288.            mov ah, byte [bus]
  289.            mov al, 10
  290.            mov bh, byte [devfn]
  291.            mov bl, byte [reg]
  292.            mov ecx, [val]
  293.            call pci_write_reg
  294.            pop ebx
  295.            ret
  296. endp
  297.  
  298. handle     equ  IOCTL.handle
  299. io_code    equ  IOCTL.io_code
  300. input      equ  IOCTL.input
  301. inp_size   equ  IOCTL.inp_size
  302. output     equ  IOCTL.output
  303. out_size   equ  IOCTL.out_size
  304.  
  305.  
  306. align 4
  307. proc srv_handler stdcall, ioctl:dword
  308.            mov esi, [ioctl]
  309.            test esi, esi
  310.            jz .err
  311.  
  312.            mov edi, [esi+handle]
  313.            cmp [edi+SRV.magic], ' SRV'
  314.            jne .fail
  315.  
  316.        cmp [edi+SRV.size], SRV.sizeof
  317.            jne .fail
  318.  
  319.            stdcall [edi+SRV.srv_proc], esi
  320.            ret
  321. .fail:
  322.            xor eax, eax
  323.            not eax
  324.            mov [esi+output], eax
  325.            mov [esi+out_size], 4
  326.            ret
  327. .err:
  328.            xor eax, eax
  329.            not eax
  330.            ret
  331. endp
  332.  
  333. ; param
  334. ;  ecx= io_control
  335. ;
  336. ; retval
  337. ;  eax= error code
  338.  
  339. align 4
  340. srv_handlerEx:
  341.            cmp ecx, OS_BASE
  342.            jae .fail
  343.  
  344.            mov eax, [ecx+handle]
  345.            cmp [eax+SRV.magic], ' SRV'
  346.            jne .fail
  347.  
  348.        cmp [eax+SRV.size], SRV.sizeof
  349.            jne .fail
  350.  
  351.            stdcall [eax+SRV.srv_proc], ecx
  352.            ret
  353. .fail:
  354.            or eax, -1
  355.            ret
  356.  
  357. restore  handle
  358. restore  io_code
  359. restore  input
  360. restore  inp_size
  361. restore  output
  362. restore  out_size
  363.  
  364. align 4
  365. proc get_service stdcall, sz_name:dword
  366.            mov eax, [sz_name]
  367.            test eax, eax
  368.            jnz @F
  369.            ret
  370. @@:
  371.            mov edx, [srv.fd]
  372. @@:
  373.            cmp edx, srv.fd-SRV_FD_OFFSET
  374.            je .not_load
  375.  
  376.            stdcall strncmp, edx, [sz_name], 16
  377.            test eax, eax
  378.            je .ok
  379.  
  380.            mov edx, [edx+SRV.fd]
  381.            jmp @B
  382. .not_load:
  383.            pop ebp
  384.            jmp load_driver
  385. .ok:
  386.            mov eax, edx
  387.            ret
  388. endp
  389.  
  390. align 4
  391. proc reg_service stdcall, name:dword, handler:dword
  392.  
  393.            push ebx
  394.  
  395.            xor eax, eax
  396.  
  397.            cmp [name], eax
  398.            je .fail
  399.  
  400.            cmp [handler], eax
  401.            je .fail
  402.  
  403.        mov eax, SRV.sizeof
  404.        call malloc
  405.            test eax, eax
  406.            jz .fail
  407.  
  408.            push esi
  409.            push edi
  410.            mov edi, eax
  411.            mov esi, [name]
  412.        movsd
  413.        movsd
  414.        movsd
  415.        movsd
  416.            pop edi
  417.            pop esi
  418.  
  419.            mov [eax+SRV.magic], ' SRV'
  420.        mov [eax+SRV.size], SRV.sizeof
  421.  
  422.            mov ebx, srv.fd-SRV_FD_OFFSET
  423.            mov edx, [ebx+SRV.fd]
  424.            mov [eax+SRV.fd], edx
  425.            mov [eax+SRV.bk], ebx
  426.            mov [ebx+SRV.fd], eax
  427.            mov [edx+SRV.bk], eax
  428.  
  429.            mov ecx, [handler]
  430.            mov [eax+SRV.srv_proc], ecx
  431.            pop ebx
  432.            ret
  433. .fail:
  434.            xor eax, eax
  435.            pop ebx
  436.            ret
  437. endp
  438.  
  439. align 4
  440. proc get_proc stdcall, exp:dword, sz_name:dword
  441.  
  442.            mov edx, [exp]
  443. .next:
  444.            mov eax, [edx]
  445.            test eax, eax
  446.            jz .end
  447.  
  448.            push edx
  449.            stdcall strncmp, eax, [sz_name], 16
  450.            pop edx
  451.            test eax, eax
  452.            jz .ok
  453.  
  454.            add edx,8
  455.            jmp .next
  456. .ok:
  457.            mov eax, [edx+4]
  458. .end:
  459.            ret
  460. endp
  461.  
  462. align 4
  463. proc get_coff_sym stdcall, pSym:dword,count:dword, sz_sym:dword
  464.  
  465. @@:
  466.            stdcall strncmp, [pSym], [sz_sym], 8
  467.            test eax,eax
  468.            jz .ok
  469.            add [pSym], 18
  470.            dec [count]
  471.            jnz @b
  472.            xor eax, eax
  473.            ret
  474. .ok:
  475.            mov eax, [pSym]
  476.            mov eax, [eax+8]
  477.            ret
  478. endp
  479.  
  480. align 4
  481. proc get_curr_task
  482.            mov eax,[CURRENT_TASK]
  483.            shl eax, 8
  484.            ret
  485. endp
  486.  
  487. align 4
  488. proc get_fileinfo stdcall, file_name:dword, info:dword
  489.            locals
  490.              cmd     dd ?
  491.              offset  dd ?
  492.                      dd ?
  493.              count   dd ?
  494.              buff    dd ?
  495.                      db ?
  496.              name    dd ?
  497.            endl
  498.  
  499.            xor eax, eax
  500.            mov ebx, [file_name]
  501.            mov ecx, [info]
  502.  
  503.            mov [cmd], 5
  504.            mov [offset], eax
  505.            mov [offset+4], eax
  506.            mov [count], eax
  507.            mov [buff], ecx
  508.            mov byte [buff+4], al
  509.            mov [name], ebx
  510.  
  511.            mov eax, 70
  512.            lea ebx, [cmd]
  513.            int 0x40
  514.            ret
  515. endp
  516.  
  517. align 4
  518. proc read_file stdcall,file_name:dword, buffer:dword, off:dword,\
  519.                                      bytes:dword
  520.            locals
  521.              cmd     dd ?
  522.              offset  dd ?
  523.                      dd ?
  524.              count   dd ?
  525.              buff    dd ?
  526.                      db ?
  527.              name    dd ?
  528.            endl
  529.  
  530.            xor eax, eax
  531.            mov ebx, [file_name]
  532.            mov ecx, [off]
  533.            mov edx, [bytes]
  534.            mov esi, [buffer]
  535.  
  536.            mov [cmd], eax
  537.            mov [offset], ecx
  538.            mov [offset+4], eax
  539.            mov [count], edx
  540.            mov [buff], esi
  541.            mov byte [buff+4], al
  542.            mov [name], ebx
  543.  
  544.            pushad
  545.            lea ebx, [cmd]
  546.            call file_system_lfn
  547.            popad
  548.            ret
  549. endp
  550.  
  551. ; description
  552. ;  allocate kernel memory and loads the specified file
  553. ;
  554. ; param
  555. ;  file_name= full path to file
  556. ;
  557. ; retval
  558. ;  eax= file image in kernel memory
  559. ;  ebx= size of file
  560. ;
  561. ; warging
  562. ;  You mast call kernel_free() to delete each file
  563. ;  loaded by the load_file() function
  564.  
  565. align 4
  566. proc load_file stdcall, file_name:dword
  567.            locals
  568.              attr       dd ?
  569.              flags      dd ?
  570.              cr_time    dd ?
  571.              cr_date    dd ?
  572.              acc_time   dd ?
  573.              acc_date   dd ?
  574.              mod_time   dd ?
  575.              mod_date   dd ?
  576.              file_size  dd ?
  577.  
  578.              file       dd ?
  579.              file2      dd ?
  580.            endl
  581.  
  582.            push esi
  583.            push edi
  584.  
  585.            lea eax, [attr]
  586.            stdcall get_fileinfo, [file_name], eax
  587.            test eax, eax
  588.            jnz .fail
  589.  
  590.            mov eax, [file_size]
  591.            cmp eax, 1024*1024*16
  592.            ja .fail
  593.  
  594.            stdcall kernel_alloc, [file_size]
  595.            mov [file], eax
  596.        test eax, eax
  597.        jz .fail
  598.  
  599.            stdcall read_file, [file_name], eax, dword 0, [file_size]
  600.            cmp ebx, [file_size]
  601.            jne .cleanup
  602.  
  603.            mov eax, [file]
  604.            cmp dword [eax], 0x4B43504B
  605.            jne .exit
  606.            mov ebx, [eax+4]
  607.            mov [file_size], ebx
  608.            stdcall kernel_alloc, ebx
  609.  
  610.            test eax, eax
  611.            jz .cleanup
  612.  
  613.            mov [file2], eax
  614.        pushfd
  615.        cli
  616.            stdcall unpack, [file], eax
  617.        popfd
  618.            stdcall kernel_free, [file]
  619.            mov eax, [file2]
  620.            mov ebx, [file_size]
  621. .exit:
  622.            push eax
  623.            lea edi, [eax+ebx]     ;cleanup remain space
  624.            mov ecx, 4096          ;from file end
  625.            and ebx, 4095
  626.            jz  @f
  627.            sub ecx, ebx
  628.            xor eax, eax
  629.            cld
  630.            rep stosb
  631. @@:
  632.            mov ebx, [file_size]
  633.            pop eax
  634.            pop edi
  635.            pop esi
  636.            ret
  637. .cleanup:
  638.            stdcall kernel_free, [file]
  639. .fail:
  640.            xor eax, eax
  641.            xor ebx, ebx
  642.            pop edi
  643.            pop esi
  644.            ret
  645. endp
  646.  
  647. align 4
  648. proc get_proc_ex stdcall, proc_name:dword, imports:dword
  649.  
  650. .look_up:
  651.            mov edx, [imports]
  652.            test edx, edx
  653.            jz .end
  654.            mov edx, [edx]
  655.            test edx, edx
  656.            jz .end
  657. .next:
  658.            mov eax, [edx]
  659.            test eax, eax
  660.            jz .next_table
  661.  
  662.            push edx
  663.        stdcall strncmp, eax, [proc_name], 256
  664.            pop edx
  665.            test eax, eax
  666.            jz .ok
  667.  
  668.            add edx,8
  669.            jmp .next
  670. .next_table:
  671.            add [imports], 4
  672.            jmp .look_up
  673. .ok:
  674.            mov eax, [edx+4]
  675.            ret
  676. .end:
  677.            xor eax, eax
  678.            ret
  679. endp
  680.  
  681. align 4
  682. proc fix_coff_symbols stdcall uses ebx esi, sec:dword, symbols:dword,\
  683.                       sym_count:dword, strings:dword, imports:dword
  684.            locals
  685.              retval dd ?
  686.            endl
  687.  
  688.            mov edi, [symbols]
  689.            mov [retval], 1
  690. .fix:
  691.            movzx ebx, [edi+CSYM.SectionNumber]
  692.            test ebx, ebx
  693.            jnz .internal
  694.            mov eax, dword [edi+CSYM.Name]
  695.            test eax, eax
  696.            jnz @F
  697.  
  698.            mov edi, [edi+4]
  699.            add edi, [strings]
  700. @@:
  701.            push edi
  702.            stdcall get_proc_ex, edi,[imports]
  703.            pop edi
  704.  
  705.            xor ebx, ebx
  706.            test eax, eax
  707.            jnz @F
  708.  
  709.            mov esi, msg_unresolved
  710.            call sys_msg_board_str
  711.            mov esi, edi
  712.            call sys_msg_board_str
  713.            mov esi, msg_CR
  714.            call sys_msg_board_str
  715.  
  716.            mov [retval],0
  717. @@:
  718.            mov edi, [symbols]
  719.            mov [edi+CSYM.Value], eax
  720.            jmp .next
  721. .internal:
  722.            cmp bx, -1
  723.            je .next
  724.            cmp bx, -2
  725.            je .next
  726.  
  727.            dec ebx
  728.            shl ebx, 3
  729.            lea ebx, [ebx+ebx*4]
  730.            add ebx, [sec]
  731.  
  732.            mov eax, [ebx+CFS.VirtualAddress]
  733.            add [edi+CSYM.Value], eax
  734. .next:
  735.            add edi, CSYM_SIZE
  736.            mov [symbols], edi
  737.            dec [sym_count]
  738.            jnz .fix
  739.            mov eax, [retval]
  740.            ret
  741. endp
  742.  
  743. align 4
  744. proc fix_coff_relocs stdcall uses ebx esi, coff:dword, sym:dword, \
  745.         delta:dword
  746.            locals
  747.              n_sec     dd ?
  748.            endl
  749.  
  750.            mov eax, [coff]
  751.            movzx ebx, [eax+CFH.nSections]
  752.            mov [n_sec], ebx
  753.            lea esi, [eax+20]
  754. .fix_sec:
  755.            mov edi, [esi+CFS.PtrReloc]
  756.            add edi, [coff]
  757.  
  758.            movzx ecx, [esi+CFS.NumReloc]
  759.            test ecx, ecx
  760.            jz .next
  761. .reloc_loop:
  762.            mov ebx, [edi+CRELOC.SymIndex]
  763.            add ebx,ebx
  764.            lea ebx,[ebx+ebx*8]
  765.            add ebx, [sym]
  766.  
  767.            mov edx, [ebx+CSYM.Value]
  768.  
  769.            cmp [edi+CRELOC.Type], 6
  770.            je .dir_32
  771.  
  772.            cmp [edi+CRELOC.Type], 20
  773.            jne .next_reloc
  774. .rel_32:
  775.            mov eax, [edi+CRELOC.VirtualAddress]
  776.            add eax, [esi+CFS.VirtualAddress]
  777.            sub edx, eax
  778.            sub edx, 4
  779.            jmp .fix
  780. .dir_32:
  781.            mov eax, [edi+CRELOC.VirtualAddress]
  782.            add eax, [esi+CFS.VirtualAddress]
  783. .fix:
  784.            add eax, [delta]
  785.            add [eax], edx
  786. .next_reloc:
  787.            add edi, 10
  788.            dec ecx
  789.            jnz .reloc_loop
  790. .next:
  791.            add esi, COFF_SECTION_SIZE
  792.            dec [n_sec]
  793.            jnz .fix_sec
  794. .exit:
  795.            ret
  796. endp
  797.  
  798. proc rebase_coff stdcall uses ebx esi, coff:dword, sym:dword, \
  799.         delta:dword
  800.            locals
  801.              n_sec     dd ?
  802.            endl
  803.  
  804.            mov eax, [coff]
  805.            movzx ebx, [eax+CFH.nSections]
  806.            mov [n_sec], ebx
  807.            lea esi, [eax+20]
  808.            mov edx, [delta]
  809. .fix_sec:
  810.            mov edi, [esi+CFS.PtrReloc]
  811.            add edi, [coff]
  812.  
  813.            movzx ecx, [esi+CFS.NumReloc]
  814.            test ecx, ecx
  815.            jz .next
  816. .reloc_loop:
  817.            cmp [edi+CRELOC.Type], 6
  818.            jne .next_reloc
  819. .dir_32:
  820.            mov eax, [edi+CRELOC.VirtualAddress]
  821.            add eax, [esi+CFS.VirtualAddress]
  822.            add [eax+edx], edx
  823. .next_reloc:
  824.            add edi, 10
  825.            dec ecx
  826.            jnz .reloc_loop
  827. .next:
  828.            add esi, COFF_SECTION_SIZE
  829.            dec [n_sec]
  830.            jnz .fix_sec
  831. .exit:
  832.            ret
  833. endp
  834.  
  835. align 4
  836. proc load_driver stdcall, driver_name:dword
  837.            locals
  838.              coff      dd ?
  839.              sym       dd ?
  840.              strings   dd ?
  841.              img_size  dd ?
  842.              img_base  dd ?
  843.              start     dd ?
  844.  
  845.              exports   dd ?   ;fake exports table
  846.                        dd ?
  847.              file_name rb 13+16+4+1      ; '/sys/drivers/<up-to-16-chars>.obj'
  848.            endl
  849.  
  850.            lea     edx, [file_name]
  851.            mov     dword [edx], '/sys'
  852.            mov     dword [edx+4], '/dri'
  853.            mov     dword [edx+8], 'vers'
  854.            mov     byte [edx+12], '/'
  855.            mov     esi, [driver_name]
  856. .redo:
  857.            lea     edx, [file_name]
  858.            lea     edi, [edx+13]
  859.            mov     ecx, 16
  860. @@:
  861.            lodsb
  862.            test    al, al
  863.            jz      @f
  864.            stosb
  865.            loop    @b
  866. @@:
  867.            mov     dword [edi], '.obj'
  868.            mov     byte [edi+4], 0
  869.            stdcall load_file, edx
  870.  
  871.            test eax, eax
  872.            jz .exit
  873.  
  874.            mov [coff], eax
  875.  
  876.            movzx ecx, [eax+CFH.nSections]
  877.            xor ebx, ebx
  878.  
  879.            lea edx, [eax+20]
  880. @@:
  881.            add ebx, [edx+CFS.SizeOfRawData]
  882.            add ebx, 15
  883.            and ebx, not 15
  884.            add edx, COFF_SECTION_SIZE
  885.            dec ecx
  886.            jnz @B
  887.            mov [img_size], ebx
  888.  
  889.            stdcall kernel_alloc, ebx
  890.            test eax, eax
  891.            jz .fail
  892.            mov [img_base], eax
  893.  
  894.            mov edi, eax
  895.            xor eax, eax
  896.            mov ecx, [img_size]
  897.            add ecx, 4095
  898.            and ecx, not 4095
  899.            shr ecx, 2
  900.            cld
  901.            rep stosd
  902.  
  903.            mov edx, [coff]
  904.            movzx ebx, [edx+CFH.nSections]
  905.            mov edi, [img_base]
  906.            lea eax, [edx+20]
  907. @@:
  908.            mov [eax+CFS.VirtualAddress], edi
  909.            mov esi, [eax+CFS.PtrRawData]
  910.            test esi, esi
  911.            jnz .copy
  912.            add edi, [eax+CFS.SizeOfRawData]
  913.            jmp .next
  914. .copy:
  915.            add esi, edx
  916.            mov ecx, [eax+CFS.SizeOfRawData]
  917.            cld
  918.            rep movsb
  919. .next:
  920.            add edi, 15
  921.            and edi, not 15
  922.            add eax, COFF_SECTION_SIZE
  923.            dec ebx
  924.            jnz @B
  925.  
  926.            mov ebx, [edx+CFH.pSymTable]
  927.            add ebx, edx
  928.            mov [sym], ebx
  929.            mov ecx, [edx+CFH.nSymbols]
  930.            add ecx,ecx
  931.            lea ecx,[ecx+ecx*8] ;ecx*=18 = nSymbols*CSYM_SIZE
  932.            add ecx, [sym]
  933.            mov [strings], ecx
  934.  
  935.            lea ebx, [exports]
  936.            mov dword [ebx], kernel_export
  937.            mov dword [ebx+4], 0
  938.            lea eax, [edx+20]
  939.  
  940.            stdcall fix_coff_symbols, eax, [sym], [edx+CFH.nSymbols],\
  941.                                      [strings], ebx
  942.            test eax, eax
  943.            jz .link_fail
  944.  
  945.            mov ebx, [coff]
  946.            stdcall fix_coff_relocs, ebx, [sym], 0
  947.  
  948.            stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szVersion
  949.            test eax, eax
  950.            jz .link_fail
  951.  
  952.            mov eax, [eax]
  953.            shr eax, 16
  954.            cmp eax, DRV_COMPAT
  955.            jb .ver_fail
  956.  
  957.            cmp eax, DRV_CURRENT
  958.            ja .ver_fail
  959.  
  960.            mov ebx, [coff]
  961.            stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szSTART
  962.            mov [start], eax
  963.  
  964.            stdcall kernel_free, [coff]
  965.  
  966.            mov ebx, [start]
  967.            stdcall ebx, DRV_ENTRY
  968.            test eax, eax
  969.            jnz .ok
  970.  
  971.            stdcall kernel_free, [img_base]
  972.            cmp     dword [file_name+13], 'SOUN'
  973.            jnz     @f
  974.            cmp     dword [file_name+17], 'D.ob'
  975.            jnz     @f
  976.            cmp     word [file_name+21], 'j'
  977.            jnz     @f
  978.            mov     esi, aSis
  979.            jmp     .redo
  980. @@:
  981.            xor eax, eax
  982.            ret
  983. .ok:
  984.            mov ebx, [img_base]
  985.            mov [eax+SRV.base], ebx
  986.            mov ecx, [start]
  987.            mov [eax+SRV.entry], ecx
  988.            ret
  989.  
  990. .ver_fail:
  991.            mov esi, msg_CR
  992.            call sys_msg_board_str
  993.            mov esi, [driver_name]
  994.            call sys_msg_board_str
  995.            mov esi, msg_CR
  996.            call sys_msg_board_str
  997.            mov esi, msg_version
  998.            call sys_msg_board_str
  999.            mov esi, msg_www
  1000.            call sys_msg_board_str
  1001.            jmp .cleanup
  1002.  
  1003. .link_fail:
  1004.            mov esi, msg_module
  1005.            call sys_msg_board_str
  1006.            mov esi, [driver_name]
  1007.            call sys_msg_board_str
  1008.            mov esi, msg_CR
  1009.            call sys_msg_board_str
  1010. .cleanup:
  1011.            stdcall kernel_free,[img_base]
  1012. .fail:
  1013.            stdcall kernel_free, [coff]
  1014. .exit:
  1015.            xor eax, eax
  1016.            ret
  1017. endp
  1018.  
  1019. ; in: edx -> COFF_SECTION struct
  1020. ; out: eax = alignment as mask for bits to drop
  1021. coff_get_align:
  1022. ; Rules:
  1023. ; - if alignment is not given, use default = 4K;
  1024. ; - if alignment is given and is no more than 4K, use it;
  1025. ; - if alignment is more than 4K, revert to 4K.
  1026.         push    ecx
  1027.         mov     cl, byte [edx+CFS.Characteristics+2]
  1028.         mov     eax, 1
  1029.         shr     cl, 4
  1030.         dec     cl
  1031.         js      .default
  1032.         cmp     cl, 12
  1033.         jbe     @f
  1034. .default:
  1035.         mov     cl, 12
  1036. @@:
  1037.         shl     eax, cl
  1038.         pop     ecx
  1039.         dec     eax
  1040.         ret
  1041.  
  1042. align 4
  1043. proc load_library stdcall, file_name:dword
  1044.            locals
  1045.              fullname  rb 260
  1046.              fileinfo  rb 40
  1047.              coff      dd ?
  1048.              img_base  dd ?
  1049.            endl
  1050.  
  1051.            cli
  1052.  
  1053. ; resolve file name
  1054.            mov ebx, [file_name]
  1055.            lea edi, [fullname+1]
  1056.            mov byte [edi-1], '/'
  1057.            stdcall get_full_file_name, edi, 259
  1058.            test al, al
  1059.            jz .fail
  1060.  
  1061. ; scan for required DLL in list of already loaded for this process,
  1062. ; ignore timestamp
  1063.            mov esi, [CURRENT_TASK]
  1064.            shl esi, 8
  1065.            lea edi, [fullname]
  1066.            mov ebx, [esi+SLOT_BASE+APPDATA.dlls_list_ptr]
  1067.            test ebx, ebx
  1068.            jz  .not_in_process
  1069.            mov esi, [ebx+HDLL.fd]
  1070. .scan_in_process:
  1071.            cmp esi, ebx
  1072.            jz .not_in_process
  1073.            mov eax, [esi+HDLL.parent]
  1074.            add eax, DLLDESCR.name
  1075.            stdcall strncmp, eax, edi, -1
  1076.            test eax, eax
  1077.            jnz .next_in_process
  1078. ; simple variant: load DLL which is already loaded in this process
  1079. ; just increment reference counters and return address of exports table
  1080.            inc [esi+HDLL.refcount]
  1081.            mov ecx, [esi+HDLL.parent]
  1082.            inc [ecx+DLLDESCR.refcount]
  1083.            mov eax, [ecx+DLLDESCR.exports]
  1084.            sub eax, [ecx+DLLDESCR.defaultbase]
  1085.            add eax, [esi+HDLL.base]
  1086.            ret
  1087. .next_in_process:
  1088.            mov esi, [esi+HDLL.fd]
  1089.            jmp .scan_in_process
  1090. .not_in_process:
  1091.  
  1092. ; scan in full list, compare timestamp
  1093.            lea eax, [fileinfo]
  1094.            stdcall get_fileinfo, edi, eax
  1095.            test eax, eax
  1096.            jnz .fail
  1097.            mov esi, [dll_list.fd]
  1098. .scan_for_dlls:
  1099.            cmp esi, dll_list
  1100.            jz .load_new
  1101.            lea eax, [esi+DLLDESCR.name]
  1102.            stdcall strncmp, eax, edi, -1
  1103.            test eax, eax
  1104.            jnz .continue_scan
  1105. .test_prev_dll:
  1106.            mov eax, dword [fileinfo+24] ; last modified time
  1107.            mov edx, dword [fileinfo+28] ; last modified date
  1108.            cmp dword [esi+DLLDESCR.timestamp], eax
  1109.            jnz .continue_scan
  1110.            cmp dword [esi+DLLDESCR.timestamp+4], edx
  1111.            jz .dll_already_loaded
  1112. .continue_scan:
  1113.            mov esi, [esi+DLLDESCR.fd]
  1114.            jmp .scan_for_dlls
  1115.  
  1116. ; new DLL
  1117. .load_new:
  1118. ; load file
  1119.            stdcall load_file, edi
  1120.            test eax, eax
  1121.            jz .fail
  1122.            mov [coff], eax
  1123.            mov dword [fileinfo+32], ebx
  1124.  
  1125. ; allocate DLLDESCR struct; size is DLLDESCR.sizeof plus size of DLL name
  1126.            mov esi, edi
  1127.            mov ecx, -1
  1128.            xor eax, eax
  1129.            repnz scasb
  1130.            not ecx
  1131.            lea eax, [ecx+DLLDESCR.sizeof]
  1132.            push ecx
  1133.            call malloc
  1134.            pop ecx
  1135.            test eax, eax
  1136.            jz .fail_and_free_coff
  1137. ; save timestamp
  1138.            lea edi, [eax+DLLDESCR.name]
  1139.            rep movsb
  1140.            mov esi, eax
  1141.            mov eax, dword [fileinfo+24]
  1142.            mov dword [esi+DLLDESCR.timestamp], eax
  1143.            mov eax, dword [fileinfo+28]
  1144.            mov dword [esi+DLLDESCR.timestamp+4], eax
  1145. ; initialize DLLDESCR struct
  1146.            and dword [esi+DLLDESCR.refcount], 0 ; no HDLLs yet; later it will be incremented
  1147.            mov [esi+DLLDESCR.fd], dll_list
  1148.            mov eax, [dll_list.bk]
  1149.            mov [dll_list.bk], esi
  1150.            mov [esi+DLLDESCR.bk], eax
  1151.            mov [eax+DLLDESCR.fd], esi
  1152.  
  1153. ; calculate size of loaded DLL
  1154.            mov edx, [coff]
  1155.            movzx ecx, [edx+CFH.nSections]
  1156.            xor ebx, ebx
  1157.  
  1158.            add edx, 20
  1159. @@:
  1160.            call coff_get_align
  1161.            add ebx, eax
  1162.            not eax
  1163.            and ebx, eax
  1164.            add ebx, [edx+CFS.SizeOfRawData]
  1165.            add edx, COFF_SECTION_SIZE
  1166.            dec ecx
  1167.            jnz @B
  1168. ; it must be nonzero and not too big
  1169.            mov [esi+DLLDESCR.size], ebx
  1170.            test ebx, ebx
  1171.            jz .fail_and_free_dll
  1172.            cmp ebx, MAX_DEFAULT_DLL_ADDR-MIN_DEFAULT_DLL_ADDR
  1173.            ja .fail_and_free_dll
  1174. ; allocate memory for kernel-side image
  1175.            stdcall kernel_alloc, ebx
  1176.            test eax, eax
  1177.            jz .fail_and_free_dll
  1178.            mov [esi+DLLDESCR.data], eax
  1179. ; calculate preferred base address
  1180.            add ebx, 0x1FFF
  1181.            and ebx, not 0xFFF
  1182.            mov ecx, [dll_cur_addr]
  1183.            lea edx, [ecx+ebx]
  1184.            cmp edx, MAX_DEFAULT_DLL_ADDR
  1185.            jb @f
  1186.            mov ecx, MIN_DEFAULT_DLL_ADDR
  1187.            lea edx, [ecx+ebx]
  1188. @@:
  1189.            mov [esi+DLLDESCR.defaultbase], ecx
  1190.            mov [dll_cur_addr], edx
  1191.  
  1192. ; copy sections and set correct values for VirtualAddress'es in headers
  1193.            push esi
  1194.            mov edx, [coff]
  1195.            movzx ebx, [edx+CFH.nSections]
  1196.            mov edi, eax
  1197.            add edx, 20
  1198.            cld
  1199. @@:
  1200.            call coff_get_align
  1201.            add ecx, eax
  1202.            add edi, eax
  1203.            not eax
  1204.            and ecx, eax
  1205.            and edi, eax
  1206.            mov [edx+CFS.VirtualAddress], ecx
  1207.            add ecx, [edx+CFS.SizeOfRawData]
  1208.            mov esi, [edx+CFS.PtrRawData]
  1209.            push ecx
  1210.            mov ecx, [edx+CFS.SizeOfRawData]
  1211.            test esi, esi
  1212.            jnz .copy
  1213.            xor eax, eax
  1214.            rep stosb
  1215.            jmp .next
  1216. .copy:
  1217.            add esi, [coff]
  1218.            rep movsb
  1219. .next:
  1220.            pop ecx
  1221.            add edx, COFF_SECTION_SIZE
  1222.            dec ebx
  1223.            jnz @B
  1224.            pop esi
  1225.  
  1226. ; save some additional data from COFF file
  1227. ; later we will use COFF header, headers for sections and symbol table
  1228. ; and also relocations table for all sections
  1229.            mov edx, [coff]
  1230.            mov ebx, [edx+CFH.pSymTable]
  1231.            mov edi, dword [fileinfo+32]
  1232.            sub edi, ebx
  1233.            jc .fail_and_free_data
  1234.            mov [esi+DLLDESCR.symbols_lim], edi
  1235.            add ebx, edx
  1236.            movzx ecx, [edx+CFH.nSections]
  1237.            lea ecx, [ecx*5]
  1238.            lea edi, [edi+ecx*8+20]
  1239.            add edx, 20
  1240. @@:
  1241.            movzx eax, [edx+CFS.NumReloc]
  1242.            lea eax, [eax*5]
  1243.            lea edi, [edi+eax*2]
  1244.            add edx, COFF_SECTION_SIZE
  1245.            sub ecx, 5
  1246.            jnz @b
  1247.            stdcall kernel_alloc, edi
  1248.            test eax, eax
  1249.            jz  .fail_and_free_data
  1250.            mov edx, [coff]
  1251.            movzx ecx, [edx+CFH.nSections]
  1252.            lea ecx, [ecx*5]
  1253.            lea ecx, [ecx*2+5]
  1254.            mov [esi+DLLDESCR.coff_hdr], eax
  1255.            push esi
  1256.            mov esi, edx
  1257.            mov edi, eax
  1258.            rep movsd
  1259.            pop esi
  1260.            mov [esi+DLLDESCR.symbols_ptr], edi
  1261.            push esi
  1262.            mov ecx, [edx+CFH.nSymbols]
  1263.            mov [esi+DLLDESCR.symbols_num], ecx
  1264.            mov ecx, [esi+DLLDESCR.symbols_lim]
  1265.            mov esi, ebx
  1266.            rep movsb
  1267.            pop esi
  1268.            mov ebx, [esi+DLLDESCR.coff_hdr]
  1269.            push esi
  1270.            movzx eax, [edx+CFH.nSections]
  1271.            lea edx, [ebx+20]
  1272. @@:
  1273.            movzx ecx, [edx+CFS.NumReloc]
  1274.            lea ecx, [ecx*5]
  1275.            mov esi, [edx+CFS.PtrReloc]
  1276.            mov [edx+CFS.PtrReloc], edi
  1277.            sub [edx+CFS.PtrReloc], ebx
  1278.            add esi, [coff]
  1279.            shr ecx, 1
  1280.            rep movsd
  1281.            adc ecx, ecx
  1282.            rep movsw
  1283.            add edx, COFF_SECTION_SIZE
  1284.            dec eax
  1285.            jnz @b
  1286.            pop esi
  1287.  
  1288. ; fixup symbols
  1289.            mov edx, ebx
  1290.            mov eax, [ebx+CFH.nSymbols]
  1291.            add edx, 20
  1292.            mov ecx, [esi+DLLDESCR.symbols_num]
  1293.            lea ecx, [ecx*9]
  1294.            add ecx, ecx
  1295.            add ecx, [esi+DLLDESCR.symbols_ptr]
  1296.  
  1297.            stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax,\
  1298.                                      ecx, 0
  1299. ;          test eax, eax
  1300. ;          jnz @F
  1301. ;
  1302. ;@@:
  1303.  
  1304.            stdcall get_coff_sym,[esi+DLLDESCR.symbols_ptr],[ebx+CFH.nSymbols],szEXPORTS
  1305.            test eax, eax
  1306.            jnz @F
  1307.  
  1308.            stdcall get_coff_sym,[esi+DLLDESCR.symbols_ptr],[ebx+CFH.nSymbols],sz_EXPORTS
  1309. @@:
  1310.            mov [esi+DLLDESCR.exports], eax
  1311.  
  1312. ; fix relocs in the hidden copy in kernel memory to default address
  1313. ; it is first fix; usually this will be enough, but second fix
  1314. ; can be necessary if real load address will not equal assumption
  1315.            mov eax, [esi+DLLDESCR.data]
  1316.            sub eax, [esi+DLLDESCR.defaultbase]
  1317.            stdcall fix_coff_relocs, ebx, [esi+DLLDESCR.symbols_ptr], eax
  1318.  
  1319.            stdcall kernel_free, [coff]
  1320.  
  1321. .dll_already_loaded:
  1322.            inc [esi+DLLDESCR.refcount]
  1323.            push esi
  1324.            call init_heap
  1325.            pop  esi
  1326.  
  1327.            mov edi, [esi+DLLDESCR.size]
  1328.            stdcall user_alloc_at, [esi+DLLDESCR.defaultbase], edi
  1329.            test eax, eax
  1330.            jnz @f
  1331.            stdcall user_alloc, edi
  1332.            test eax, eax
  1333.            jz  .fail_and_dereference
  1334. @@:
  1335.            mov [img_base], eax
  1336.            mov eax, HDLL.sizeof
  1337.            call malloc
  1338.            test eax, eax
  1339.            jz  .fail_and_free_user
  1340.            mov ebx, [CURRENT_TASK]
  1341.            shl ebx, 5
  1342.            mov edx, [CURRENT_TASK+ebx+TASKDATA.pid]
  1343.            mov [eax+HDLL.pid], edx
  1344.            push eax
  1345.            call init_dlls_in_thread
  1346.            pop  ebx
  1347.            test eax, eax
  1348.            jz  .fail_and_free_user
  1349.            mov edx, [eax+HDLL.fd]
  1350.            mov [ebx+HDLL.fd], edx
  1351.            mov [ebx+HDLL.bk], eax
  1352.            mov [eax+HDLL.fd], ebx
  1353.            mov [edx+HDLL.bk], ebx
  1354.            mov eax, ebx
  1355.            mov ebx, [img_base]
  1356.            mov [eax+HDLL.base], ebx
  1357.            mov [eax+HDLL.size], edi
  1358.            mov [eax+HDLL.refcount], 1
  1359.            mov [eax+HDLL.parent], esi
  1360.            mov edx, ebx
  1361.            shr edx, 12
  1362.            or dword [page_tabs+(edx-1)*4], DONT_FREE_BLOCK
  1363. ; copy entries of page table from kernel-side image to usermode
  1364. ; use copy-on-write for user-mode image, so map as readonly
  1365.            xor edi, edi
  1366.            mov ecx, [esi+DLLDESCR.data]
  1367.            shr ecx, 12
  1368. .map_pages_loop:
  1369.            mov eax, [page_tabs+ecx*4]
  1370.            and eax, not 0xFFF
  1371.            or al, PG_USER
  1372.            xchg eax, [page_tabs+edx*4]
  1373.            test al, 1
  1374.            jz @f
  1375.            call free_page
  1376. @@:
  1377.            invlpg [ebx+edi]
  1378.            inc ecx
  1379.            inc edx
  1380.            add edi, 0x1000
  1381.            cmp edi, [esi+DLLDESCR.size]
  1382.            jb .map_pages_loop
  1383.  
  1384. ; if real user-mode base is not equal to preferred base, relocate image
  1385.            sub ebx, [esi+DLLDESCR.defaultbase]
  1386.            jz @f
  1387.            stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx
  1388. @@:
  1389.  
  1390.            mov eax, [esi+DLLDESCR.exports]
  1391.            sub eax, [esi+DLLDESCR.defaultbase]
  1392.            add eax, [img_base]
  1393.            ret
  1394. .fail_and_free_data:
  1395.            stdcall kernel_free, [esi+DLLDESCR.data]
  1396. .fail_and_free_dll:
  1397.            mov eax, esi
  1398.            call free
  1399. .fail_and_free_coff:
  1400.            stdcall kernel_free, [coff]
  1401. .fail:
  1402.            xor eax, eax
  1403.            ret
  1404. .fail_and_free_user:
  1405.            stdcall user_free, [img_base]
  1406. .fail_and_dereference:
  1407.            mov eax, 1   ; delete 1 reference
  1408.            call dereference_dll
  1409.            xor eax, eax
  1410.            ret
  1411. endp
  1412.  
  1413. ; initialize [APPDATA.dlls_list_ptr] for given thread
  1414. ; DLL is per-process object, so APPDATA.dlls_list_ptr must be
  1415. ; kept in sync for all threads of one process.
  1416. ; out: eax = APPDATA.dlls_list_ptr if all is OK,
  1417. ; NULL if memory allocation failed
  1418. init_dlls_in_thread:
  1419.         mov     ebx, [current_slot]
  1420.         mov     eax, [ebx+APPDATA.dlls_list_ptr]
  1421.         test    eax, eax
  1422.         jnz     .ret
  1423.         push    [ebx+APPDATA.dir_table]
  1424.         mov     eax, 8
  1425.         call    malloc
  1426.         pop     edx
  1427.         test    eax, eax
  1428.         jz      .ret
  1429.         mov     [eax], eax
  1430.         mov     [eax+4], eax
  1431.         mov     ecx, [TASK_COUNT]
  1432.         mov     ebx, SLOT_BASE+256
  1433. .set:
  1434.         cmp     [ebx+APPDATA.dir_table], edx
  1435.         jnz     @f
  1436.         mov     [ebx+APPDATA.dlls_list_ptr], eax
  1437. @@:
  1438.         add     ebx, 256
  1439.         dec     ecx
  1440.         jnz     .set
  1441. .ret:
  1442.         ret
  1443.  
  1444. ; in: eax = number of references to delete, esi -> DLLDESCR struc
  1445. dereference_dll:
  1446.         sub     [esi+DLLDESCR.refcount], eax
  1447.         jnz     .ret
  1448.         mov     eax, [esi+DLLDESCR.fd]
  1449.         mov     edx, [esi+DLLDESCR.bk]
  1450.         mov     [eax+DLLDESCR.bk], edx
  1451.         mov     [edx+DLLDESCR.fd], eax
  1452.         stdcall kernel_free, [esi+DLLDESCR.coff_hdr]
  1453.         stdcall kernel_free, [esi+DLLDESCR.data]
  1454.         mov     eax, esi
  1455.         call    free
  1456. .ret:
  1457.         ret
  1458.  
  1459. destroy_hdll:
  1460.         push    ebx ecx esi edi
  1461.         push    eax
  1462.         mov     ebx, [eax+HDLL.base]
  1463.         mov     esi, [eax+HDLL.parent]
  1464.         mov     edx, [esi+DLLDESCR.size]
  1465. ; The following actions require the context of application where HDLL is mapped.
  1466. ; However, destroy_hdll can be called in the context of OS thread when
  1467. ; cleaning up objects created by the application which is destroyed.
  1468. ; So remember current cr3 and set it to page table of target.
  1469.         mov     eax, [ecx+APPDATA.dir_table]
  1470. ; Because we cheat with cr3, disable interrupts: task switch would restore
  1471. ; page table from APPDATA of current thread.
  1472. ; Also set [current_slot] because it is used by user_free.
  1473.         pushf
  1474.         cli
  1475.         push    [current_slot]
  1476.         mov     [current_slot], ecx
  1477.         mov     ecx, cr3
  1478.         push    ecx
  1479.         mov     cr3, eax
  1480.         push    ebx     ; argument for user_free
  1481.         mov     eax, ebx
  1482.         shr     ebx, 12
  1483.         push    ebx
  1484.         mov     esi, [esi+DLLDESCR.data]
  1485.         shr     esi, 12
  1486. .unmap_loop:
  1487.         push    eax
  1488.         mov     eax, 2
  1489.         xchg    eax, [page_tabs+ebx*4]
  1490.         mov     ecx, [page_tabs+esi*4]
  1491.         and     eax, not 0xFFF
  1492.         and     ecx, not 0xFFF
  1493.         cmp     eax, ecx
  1494.         jz      @f
  1495.         call    free_page
  1496. @@:
  1497.         pop     eax
  1498.         invlpg  [eax]
  1499.         add     eax, 0x1000
  1500.         inc     ebx
  1501.         inc     esi
  1502.         sub     edx, 0x1000
  1503.         ja      .unmap_loop
  1504.         pop     ebx
  1505.         and     dword [page_tabs+(ebx-1)*4], not DONT_FREE_BLOCK
  1506.         call    user_free
  1507. ; Restore context.
  1508.         pop     eax
  1509.         mov     cr3, eax
  1510.         pop     [current_slot]
  1511.         popf
  1512. ; Ok, cheating is done.
  1513.         pop     eax
  1514.         push    eax
  1515.         mov     esi, [eax+HDLL.parent]
  1516.         mov     eax, [eax+HDLL.refcount]
  1517.         call    dereference_dll
  1518.         pop     eax
  1519.         mov     edx, [eax+HDLL.bk]
  1520.         mov     ebx, [eax+HDLL.fd]
  1521.         mov     [ebx+HDLL.bk], edx
  1522.         mov     [edx+HDLL.fd], ebx
  1523.         call    free
  1524.         pop     edi esi ecx ebx
  1525.         ret
  1526.  
  1527. ; ecx -> APPDATA for slot, esi = dlls_list_ptr
  1528. destroy_all_hdlls:
  1529.         test    esi, esi
  1530.         jz      .ret
  1531. .loop:
  1532.         mov     eax, [esi+HDLL.fd]
  1533.         cmp     eax, esi
  1534.         jz      free
  1535.         call    destroy_hdll
  1536.         jmp     .loop
  1537. .ret:
  1538.         ret
  1539.  
  1540. align 4
  1541. stop_all_services:
  1542.        push ebp
  1543.            mov edx, [srv.fd]
  1544. .next:
  1545.            cmp edx,  srv.fd-SRV_FD_OFFSET
  1546.            je .done
  1547.            cmp [edx+SRV.magic], ' SRV'
  1548.            jne .next
  1549.        cmp [edx+SRV.size], SRV.sizeof
  1550.            jne .next
  1551.  
  1552.            mov ebx, [edx+SRV.entry]
  1553.            mov edx, [edx+SRV.fd]
  1554.            test ebx, ebx
  1555.            jz .next
  1556.  
  1557.            push edx
  1558.        mov ebp, esp
  1559.        push  0
  1560.        push -1
  1561.        call ebx
  1562.        mov esp, ebp
  1563.            pop edx
  1564.            jmp .next
  1565. .done:
  1566.        pop ebp
  1567.            ret
  1568.  
  1569. ; param
  1570. ;  eax= size
  1571. ;  ebx= pid
  1572.  
  1573. align 4
  1574. create_kernel_object:
  1575.  
  1576.            push ebx
  1577.            call malloc
  1578.            pop ebx
  1579.            test eax, eax
  1580.            jz .fail
  1581.  
  1582.            mov ecx,[current_slot]
  1583.            add ecx, APP_OBJ_OFFSET
  1584.  
  1585.            pushfd
  1586.            cli
  1587.            mov edx, [ecx+APPOBJ.fd]
  1588.            mov [eax+APPOBJ.fd], edx
  1589.            mov [eax+APPOBJ.bk], ecx
  1590.            mov [eax+APPOBJ.pid], ebx
  1591.  
  1592.            mov [ecx+APPOBJ.fd], eax
  1593.            mov [edx+APPOBJ.bk], eax
  1594.            popfd
  1595. .fail:
  1596.            ret
  1597.  
  1598. ; param
  1599. ;  eax= object
  1600.  
  1601. align 4
  1602. destroy_kernel_object:
  1603.  
  1604.            pushfd
  1605.            cli
  1606.            mov ebx, [eax+APPOBJ.fd]
  1607.            mov ecx, [eax+APPOBJ.bk]
  1608.            mov [ebx+APPOBJ.bk], ecx
  1609.            mov [ecx+APPOBJ.fd], ebx
  1610.            popfd
  1611.  
  1612.            xor edx, edx        ;clear common header
  1613.            mov [eax], edx
  1614.            mov [eax+4], edx
  1615.            mov [eax+8], edx
  1616.            mov [eax+12], edx
  1617.            mov [eax+16], edx
  1618.  
  1619.            call free           ;release object memory
  1620.            ret
  1621.  
  1622.  
  1623.  
  1624. if 0
  1625.  
  1626. irq:
  1627.  
  1628. .irq0:
  1629.            pusfd
  1630.            pushad
  1631.            push IRQ_0
  1632.            jmp .master
  1633. .irq_1:
  1634.            pusfd
  1635.            pushad
  1636.            push IRQ_1
  1637.            jmp .master
  1638.  
  1639. .master:
  1640.            mov ax, app_data
  1641.            mov ds, eax
  1642.            mov es, eax
  1643.            mov ebx, [esp+4]  ;IRQ_xx
  1644.            mov eax, [irq_handlers+ebx+4]
  1645.            call intr_handler
  1646.            mov ecx, [esp+4]
  1647.            cmp [irq_actids+ecx*4], 0
  1648.            je @F
  1649.            in al, 0x21
  1650.            bts eax, ecx
  1651.            out 0x21, al
  1652.            mov al, 0x20
  1653.            out 0x20, al
  1654.            jmp .restart
  1655.  
  1656. .slave:
  1657.            mov ax, app_data
  1658.            mov ds, eax
  1659.            mov es, eax
  1660.            mov ebx, [esp+4]  ;IRQ_xx
  1661.            mov eax, [irq_handlers+ebx+4]
  1662.            call intr_handler
  1663.            mov ecx, [esp+4]
  1664.            sub ecx, 8
  1665.            cmp [irq_actids+ecx*4], 0
  1666.            je @F
  1667.            in al, 0xA1
  1668.            bts eax, ecx
  1669.            out 0xA1, al
  1670.            mov al, 0x20
  1671.            out 0xA0, al
  1672.            out 0x20, al
  1673. .restart:
  1674.            mov ebx, [next_slot]
  1675.            test ebx, ebx
  1676.            jz @F
  1677.            mov [next_task],0
  1678.            mov esi, [prev_slot]
  1679.            call do_change_task
  1680.            add esp, 4
  1681.            iretd
  1682.  
  1683. end if
  1684.  
  1685.  
  1686.  
  1687.  
  1688.