Subversion Repositories Kolibri OS

Rev

Rev 1292 | Rev 1316 | 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: 1296 $
  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 ebx, [esi+SLOT_BASE+APP_OBJ_OFFSET]
  1068.            mov esi, [ebx+APPOBJ.fd]
  1069.            lea edi, [fullname]
  1070. .scan_in_process:
  1071.            cmp esi, ebx
  1072.            jz .not_in_process
  1073.            cmp dword [esi+APPOBJ.magic], 'HDLL'
  1074.            jnz .next_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+APPOBJ.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 ebx, [CURRENT_TASK]
  1339.            shl ebx, 5
  1340.            mov ebx, [CURRENT_TASK+ebx+TASKDATA.pid]
  1341.            mov eax, HDLL.sizeof
  1342.            call create_kernel_object
  1343.            test eax, eax
  1344.            jz .fail_and_free_user
  1345.            mov [eax+APPOBJ.magic], 'HDLL'
  1346.            mov [eax+APPOBJ.destroy], destroy_hdll
  1347.            mov ebx, [img_base]
  1348.            mov [eax+HDLL.base], ebx
  1349.            mov [eax+HDLL.size], edi
  1350.            mov [eax+HDLL.refcount], 1
  1351.            mov [eax+HDLL.parent], esi
  1352.            mov edx, ebx
  1353.            shr edx, 12
  1354.            or dword [page_tabs+(edx-1)*4], DONT_FREE_BLOCK
  1355. ; copy entries of page table from kernel-side image to usermode
  1356. ; use copy-on-write for user-mode image, so map as readonly
  1357.            xor edi, edi
  1358.            mov ecx, [esi+DLLDESCR.data]
  1359.            shr ecx, 12
  1360. .map_pages_loop:
  1361.            mov eax, [page_tabs+ecx*4]
  1362.            and eax, not 0xFFF
  1363.            or al, PG_USER
  1364.            xchg eax, [page_tabs+edx*4]
  1365.            test al, 1
  1366.            jz @f
  1367.            call free_page
  1368. @@:
  1369.            invlpg [ebx+edi]
  1370.            inc ecx
  1371.            inc edx
  1372.            add edi, 0x1000
  1373.            cmp edi, [esi+DLLDESCR.size]
  1374.            jb .map_pages_loop
  1375.  
  1376. ; if real user-mode base is not equal to preferred base, relocate image
  1377.            mov ebx, [img_base]
  1378.            sub ebx, [esi+DLLDESCR.defaultbase]
  1379.            jz @f
  1380.            stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx
  1381. @@:
  1382.  
  1383.            mov eax, [esi+DLLDESCR.exports]
  1384.            sub eax, [esi+DLLDESCR.defaultbase]
  1385.            add eax, [img_base]
  1386.            ret
  1387. .fail_and_free_data:
  1388.            stdcall kernel_free, [esi+DLLDESCR.data]
  1389. .fail_and_free_dll:
  1390.            mov eax, esi
  1391.            call free
  1392. .fail_and_free_coff:
  1393.            stdcall kernel_free, [coff]
  1394. .fail:
  1395.            xor eax, eax
  1396.            ret
  1397. .fail_and_free_user:
  1398.            stdcall user_free, [img_base]
  1399. .fail_and_dereference:
  1400.            mov eax, 1   ; delete 1 reference
  1401.            call dereference_dll
  1402.            xor eax, eax
  1403.            ret
  1404. endp
  1405.  
  1406. ; in: eax = number of references to delete, esi -> DLLDESCR struc
  1407. dereference_dll:
  1408.         sub     [esi+DLLDESCR.refcount], eax
  1409.         jnz     .ret
  1410.         mov     eax, [esi+DLLDESCR.fd]
  1411.         mov     edx, [esi+DLLDESCR.bk]
  1412.         mov     [eax+DLLDESCR.bk], edx
  1413.         mov     [edx+DLLDESCR.fd], eax
  1414.         stdcall kernel_free, [esi+DLLDESCR.coff_hdr]
  1415.         stdcall kernel_free, [esi+DLLDESCR.data]
  1416.         mov     eax, esi
  1417.         call    free
  1418. .ret:
  1419.         ret
  1420.  
  1421. destroy_hdll:
  1422.         push    ebx esi edi
  1423.         push    eax
  1424.         mov     ebx, [eax+HDLL.base]
  1425.         mov     esi, [eax+HDLL.parent]
  1426.         mov     edx, [esi+DLLDESCR.size]
  1427. ; The following actions require the context of application where HDLL is mapped.
  1428. ; However, destroy_hdll can be called in the context of OS thread when
  1429. ; cleaning up objects created by the application which is destroyed.
  1430. ; So remember current cr3 and set it to page table of target.
  1431.         mov     eax, [eax+HDLL.pid]
  1432.         call    pid_to_slot
  1433.         shl     eax, 8
  1434.         add     eax, SLOT_BASE
  1435.         mov     ecx, [eax+APPDATA.dir_table]
  1436. ; Because we cheat with cr3, disable interrupts: task switch would restore
  1437. ; page table from APPDATA of current thread.
  1438. ; Also set [current_slot] because it is used by user_free.
  1439.         pushf
  1440.         cli
  1441.         push    [current_slot]
  1442.         mov     [current_slot], eax
  1443.         mov     eax, cr3
  1444.         push    eax
  1445.         mov     cr3, ecx
  1446.         push    ebx     ; argument for user_free
  1447.         mov     eax, ebx
  1448.         shr     ebx, 12
  1449.         push    ebx
  1450.         mov     esi, [esi+DLLDESCR.data]
  1451.         shr     esi, 12
  1452. .unmap_loop:
  1453.         push    eax
  1454.         mov     eax, 2
  1455.         xchg    eax, [page_tabs+ebx*4]
  1456.         mov     ecx, [page_tabs+esi*4]
  1457.         and     eax, not 0xFFF
  1458.         and     ecx, not 0xFFF
  1459.         cmp     eax, ecx
  1460.         jz      @f
  1461.         call    free_page
  1462. @@:
  1463.         pop     eax
  1464.         invlpg  [eax]
  1465.         add     eax, 0x1000
  1466.         inc     ebx
  1467.         inc     esi
  1468.         sub     edx, 0x1000
  1469.         ja      .unmap_loop
  1470.         pop     ebx
  1471.         and     dword [page_tabs+(ebx-1)*4], not DONT_FREE_BLOCK
  1472.         call    user_free
  1473. ; Restore context.
  1474.         pop     eax
  1475.         mov     cr3, eax
  1476.         pop     [current_slot]
  1477.         popf
  1478. ; Ok, cheating is done.
  1479.         pop     eax
  1480.         push    eax
  1481.         mov     esi, [eax+HDLL.parent]
  1482.         mov     eax, [eax+HDLL.refcount]
  1483.         call    dereference_dll
  1484.         pop     eax
  1485.         call    destroy_kernel_object
  1486.         pop     edi esi ebx
  1487.         ret
  1488.  
  1489. align 4
  1490. stop_all_services:
  1491.        push ebp
  1492.            mov edx, [srv.fd]
  1493. .next:
  1494.            cmp edx,  srv.fd-SRV_FD_OFFSET
  1495.            je .done
  1496.            cmp [edx+SRV.magic], ' SRV'
  1497.            jne .next
  1498.        cmp [edx+SRV.size], SRV.sizeof
  1499.            jne .next
  1500.  
  1501.            mov ebx, [edx+SRV.entry]
  1502.            mov edx, [edx+SRV.fd]
  1503.            test ebx, ebx
  1504.            jz .next
  1505.  
  1506.            push edx
  1507.            stdcall ebx, dword -1
  1508.            pop edx
  1509.            jmp .next
  1510. .done:
  1511.        pop ebp
  1512.            ret
  1513.  
  1514. ; param
  1515. ;  eax= size
  1516. ;  ebx= pid
  1517.  
  1518. align 4
  1519. create_kernel_object:
  1520.  
  1521.            push ebx
  1522.            call malloc
  1523.            pop ebx
  1524.            test eax, eax
  1525.            jz .fail
  1526.  
  1527.            mov ecx,[current_slot]
  1528.            add ecx, APP_OBJ_OFFSET
  1529.  
  1530.            pushfd
  1531.            cli
  1532.            mov edx, [ecx+APPOBJ.fd]
  1533.            mov [eax+APPOBJ.fd], edx
  1534.            mov [eax+APPOBJ.bk], ecx
  1535.            mov [eax+APPOBJ.pid], ebx
  1536.  
  1537.            mov [ecx+APPOBJ.fd], eax
  1538.            mov [edx+APPOBJ.bk], eax
  1539.            popfd
  1540. .fail:
  1541.            ret
  1542.  
  1543. ; param
  1544. ;  eax= object
  1545.  
  1546. align 4
  1547. destroy_kernel_object:
  1548.  
  1549.            pushfd
  1550.            cli
  1551.            mov ebx, [eax+APPOBJ.fd]
  1552.            mov ecx, [eax+APPOBJ.bk]
  1553.            mov [ebx+APPOBJ.bk], ecx
  1554.            mov [ecx+APPOBJ.fd], ebx
  1555.            popfd
  1556.  
  1557.            xor edx, edx        ;clear common header
  1558.            mov [eax], edx
  1559.            mov [eax+4], edx
  1560.            mov [eax+8], edx
  1561.            mov [eax+12], edx
  1562.            mov [eax+16], edx
  1563.  
  1564.            call free           ;release object memory
  1565.            ret
  1566.  
  1567.  
  1568.  
  1569. if 0
  1570.  
  1571. irq:
  1572.  
  1573. .irq0:
  1574.            pusfd
  1575.            pushad
  1576.            push IRQ_0
  1577.            jmp .master
  1578. .irq_1:
  1579.            pusfd
  1580.            pushad
  1581.            push IRQ_1
  1582.            jmp .master
  1583.  
  1584. .master:
  1585.            mov ax, app_data
  1586.            mov ds, eax
  1587.            mov es, eax
  1588.            mov ebx, [esp+4]  ;IRQ_xx
  1589.            mov eax, [irq_handlers+ebx+4]
  1590.            call intr_handler
  1591.            mov ecx, [esp+4]
  1592.            cmp [irq_actids+ecx*4], 0
  1593.            je @F
  1594.            in al, 0x21
  1595.            bts eax, ecx
  1596.            out 0x21, al
  1597.            mov al, 0x20
  1598.            out 0x20, al
  1599.            jmp .restart
  1600.  
  1601. .slave:
  1602.            mov ax, app_data
  1603.            mov ds, eax
  1604.            mov es, eax
  1605.            mov ebx, [esp+4]  ;IRQ_xx
  1606.            mov eax, [irq_handlers+ebx+4]
  1607.            call intr_handler
  1608.            mov ecx, [esp+4]
  1609.            sub ecx, 8
  1610.            cmp [irq_actids+ecx*4], 0
  1611.            je @F
  1612.            in al, 0xA1
  1613.            bts eax, ecx
  1614.            out 0xA1, al
  1615.            mov al, 0x20
  1616.            out 0xA0, al
  1617.            out 0x20, al
  1618. .restart:
  1619.            mov ebx, [next_slot]
  1620.            test ebx, ebx
  1621.            jz @F
  1622.            mov [next_task],0
  1623.            mov esi, [prev_slot]
  1624.            call do_change_task
  1625.            add esp, 4
  1626.            iretd
  1627.  
  1628. end if
  1629.  
  1630.  
  1631.  
  1632.  
  1633.