Subversion Repositories Kolibri OS

Rev

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