Subversion Repositories Kolibri OS

Rev

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