Subversion Repositories Kolibri OS

Rev

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