Subversion Repositories Kolibri OS

Rev

Rev 9917 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2022. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 10002 $
  9.  
  10.  
  11. align 4
  12. proc alloc_page
  13.  
  14.         pushfd
  15.         cli
  16.         push    ebx
  17.  
  18.         cmp     [pg_data.pages_free], 1
  19.         jle     .out_of_memory
  20.  
  21.  
  22.         mov     ebx, [page_start]
  23.         mov     ecx, [page_end]
  24. .l1:
  25.         bsf     eax, [ebx];
  26.         jnz     .found
  27.         add     ebx, 4
  28.         cmp     ebx, ecx
  29.         jb      .l1
  30.         pop     ebx
  31.         popfd
  32.         xor     eax, eax
  33.         ret
  34. .found:
  35.  
  36.         dec     [pg_data.pages_free]
  37.         jz      .out_of_memory
  38.  
  39.         btr     [ebx], eax
  40.         mov     [page_start], ebx
  41.         sub     ebx, sys_pgmap
  42.         lea     eax, [eax+ebx*8]
  43.         shl     eax, 12
  44. ;       dec [pg_data.pages_free]
  45.         pop     ebx
  46.         popfd
  47.         ret
  48.  
  49. .out_of_memory:
  50.         mov     [pg_data.pages_free], 1
  51.         xor     eax, eax
  52.         pop     ebx
  53.         popfd
  54.         ret
  55.  
  56. endp
  57.  
  58. align 4
  59. proc alloc_pages stdcall, count:dword
  60.         pushfd
  61.         push    ebx
  62.         push    edi
  63.         cli
  64.         mov     eax, [count]
  65.         add     eax, 7
  66.         shr     eax, 3
  67.         mov     [count], eax
  68.  
  69.         mov     ebx, [pg_data.pages_free]
  70.         sub     ebx, 9
  71.         js      .out_of_memory
  72.         shr     ebx, 3
  73.         cmp     eax, ebx
  74.         jg      .out_of_memory
  75.  
  76.         mov     ecx, [page_start]
  77.         mov     ebx, [page_end]
  78. .find:
  79.         mov     edx, [count]
  80.         mov     edi, ecx
  81.   .match:
  82.         cmp     byte [ecx], 0xFF
  83.         jne     .next
  84.         dec     edx
  85.         jz      .ok
  86.         inc     ecx
  87.         cmp     ecx, ebx
  88.         jb      .match
  89.   .out_of_memory:
  90.   .fail:
  91.         xor     eax, eax
  92.         pop     edi
  93.         pop     ebx
  94.         popfd
  95.         ret
  96.   .next:
  97.         inc     ecx
  98.         cmp     ecx, ebx
  99.         jb      .find
  100.         pop     edi
  101.         pop     ebx
  102.         popfd
  103.         xor     eax, eax
  104.         ret
  105.   .ok:
  106.         sub     ecx, edi
  107.         inc     ecx
  108.         push    esi
  109.         mov     esi, edi
  110.         xor     eax, eax
  111.         rep stosb
  112.         sub     esi, sys_pgmap
  113.         shl     esi, 3+12
  114.         mov     eax, esi
  115.         mov     ebx, [count]
  116.         shl     ebx, 3
  117.         sub     [pg_data.pages_free], ebx
  118.         pop     esi
  119.         pop     edi
  120.         pop     ebx
  121.         popfd
  122.         ret
  123. endp
  124.  
  125. align 4
  126. ;proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword
  127. map_page:
  128.         push    ebx
  129.         mov     eax, [esp+12]              ; phis_addr
  130.         or      eax, [esp+16]              ; flags
  131.         and     eax, [pte_valid_mask]
  132.         mov     ebx, [esp+8]               ; lin_addr
  133.         shr     ebx, 12
  134.         mov     [page_tabs + ebx*4], eax
  135.         mov     eax, [esp+8]               ; lin_addr
  136.         pop     ebx
  137.         invlpg  [eax]
  138.         ret     12
  139.  
  140. align 4
  141. map_space:    ;not implemented
  142.  
  143.  
  144.         ret
  145.  
  146.  
  147. align 4
  148. proc free_page
  149. ;arg:  eax  page address
  150.         pushfd
  151.         cli
  152.         shr     eax, 12                       ;page index
  153.         bts     dword [sys_pgmap], eax        ;that's all!
  154.         cmc
  155.         adc     [pg_data.pages_free], 0
  156.         shr     eax, 3
  157.         and     eax, not 3                    ;dword offset from page_map
  158.         add     eax, sys_pgmap
  159.         cmp     [page_start], eax
  160.         ja      @f
  161.         popfd
  162.         ret
  163. @@:
  164.         mov     [page_start], eax
  165.         popfd
  166.         ret
  167. endp
  168.  
  169. align 4
  170. proc map_io_mem stdcall, base:dword, size:dword, flags:dword
  171.  
  172.         push    ebx
  173.         push    edi
  174.         mov     eax, [size]
  175.         add     eax, [base]
  176.         add     eax, PAGE_SIZE-1
  177.         and     eax, -PAGE_SIZE
  178.         mov     ecx, [base]
  179.         and     ecx, -PAGE_SIZE
  180.         sub     eax, ecx
  181.         mov     [size], eax
  182.  
  183.         stdcall alloc_kernel_space, eax
  184.         test    eax, eax
  185.         jz      .fail
  186.         push    eax
  187.  
  188.         mov     edi, PAGE_SIZE
  189.         mov     ebx, eax
  190.         mov     ecx, [size]
  191.         mov     edx, [base]
  192.         shr     eax, 12
  193.         shr     ecx, 12
  194.         or      edx, [flags]
  195.         and     edx, [pte_valid_mask]
  196. @@:
  197.         mov     [page_tabs + eax*4], edx
  198.         invlpg  [ebx]
  199.         inc     eax
  200.         add     ebx, edi
  201.         add     edx, edi
  202.         loop    @B
  203.  
  204.         pop     eax
  205.         mov     edx, [base]
  206.         and     edx, PAGE_SIZE-1
  207.         add     eax, edx
  208. .fail:
  209.         pop     edi
  210.         pop     ebx
  211.         ret
  212. endp
  213.  
  214. ; param
  215. ;  eax= page base + page flags
  216. ;  ebx= linear address
  217. ;  ecx= count
  218.  
  219. align 4
  220. commit_pages:
  221.         test    ecx, ecx
  222.         jz      .fail
  223.  
  224.         push    edi
  225.         push    eax
  226.         push    ecx
  227.         mov     ecx, pg_data.mutex
  228.         call    mutex_lock
  229.         pop     ecx
  230.         pop     eax
  231.  
  232.         and     eax, [pte_valid_mask ]
  233.         mov     edi, ebx
  234.         shr     edi, 12
  235.         lea     edi, [page_tabs + edi*4]
  236. @@:
  237.         stosd
  238.         invlpg  [ebx]
  239.         add     eax, PAGE_SIZE
  240.         add     ebx, PAGE_SIZE
  241.         loop    @B
  242.  
  243.         pop     edi
  244.  
  245.         mov     ecx, pg_data.mutex
  246.         call    mutex_unlock
  247. .fail:
  248.         ret
  249.  
  250.  
  251. ; param
  252. ;  eax= base
  253. ;  ecx= count
  254.  
  255. align 4
  256. release_pages:
  257.  
  258.         push    ebp
  259.         push    esi
  260.         push    edi
  261.         push    ebx
  262.  
  263.         mov     esi, eax
  264.         mov     edi, eax
  265.  
  266.         shr     esi, 12
  267.         lea     esi, [page_tabs + esi*4]
  268.  
  269.         push    ecx
  270.         mov     ecx, pg_data.mutex
  271.         call    mutex_lock
  272.         pop     ecx
  273.  
  274.         mov     ebp, [pg_data.pages_free]
  275.         mov     ebx, [page_start]
  276.         mov     edx, sys_pgmap
  277. @@:
  278.         xor     eax, eax
  279.         xchg    eax, [esi]
  280.         invlpg  [edi]
  281.  
  282.         test    eax, 1
  283.         jz      .next
  284.  
  285.         shr     eax, 12
  286.         bts     [edx], eax
  287.         cmc
  288.         adc     ebp, 0
  289.         shr     eax, 3
  290.         and     eax, -4
  291.         add     eax, edx
  292.         cmp     eax, ebx
  293.         jae     .next
  294.  
  295.         mov     ebx, eax
  296. .next:
  297.         add     edi, PAGE_SIZE
  298.         add     esi, 4
  299.         loop    @B
  300.  
  301.         mov     [pg_data.pages_free], ebp
  302.         mov     ecx, pg_data.mutex
  303.         call    mutex_unlock
  304.  
  305.         pop     ebx
  306.         pop     edi
  307.         pop     esi
  308.         pop     ebp
  309.         ret
  310.  
  311. ; param
  312. ;  eax= base
  313. ;  ecx= count
  314.  
  315. align 4
  316. unmap_pages:
  317.  
  318.         push    edi
  319.  
  320.         mov     edi, eax
  321.         mov     edx, eax
  322.  
  323.         shr     edi, 10
  324.         add     edi, page_tabs
  325.  
  326.         xor     eax, eax
  327. @@:
  328.         stosd
  329.         invlpg  [edx]
  330.         add     edx, PAGE_SIZE
  331.         loop    @b
  332.  
  333.         pop     edi
  334.         ret
  335.  
  336.  
  337. align 4
  338. proc map_page_table stdcall, lin_addr:dword, phis_addr:dword
  339.         push    ebx
  340.         mov     ebx, [lin_addr]
  341.         shr     ebx, 22
  342.         mov     eax, [phis_addr]
  343.         and     eax, -PAGE_SIZE
  344.         or      eax, PG_UWR
  345.         mov     dword [master_tab + ebx*4], eax
  346.         mov     eax, [lin_addr]
  347.         shr     eax, 10
  348.         add     eax, page_tabs
  349.         invlpg  [eax]
  350.         pop     ebx
  351.         ret
  352. endp
  353.  
  354. uglobal
  355. sb16_buffer_allocated db 0
  356. endg
  357.  
  358. ; Allocates [.size] bytes so that the target memory block
  359. ; is inside one 64K page for 24-bit DMA controller,
  360. ; that is, somewhere between 00xx0000h and 00xxFFFFh.
  361. proc alloc_dma24
  362. ; Implementation note.
  363. ; The only user of that function is SB16 driver,
  364. ; so just return a statically allocated buffer.
  365. virtual at esp
  366.                 dd      ? ; return address
  367. .size           dd      ?
  368. end virtual
  369.         cmp     [sb16_buffer_allocated], 0
  370.         jnz     .fail
  371.         inc     [sb16_buffer_allocated]
  372.         mov     eax, SB16Buffer
  373.         ret     4
  374. .fail:
  375.         xor     eax, eax
  376.         ret     4
  377. endp
  378.  
  379. ; Allocates a physical page for master page table
  380. ; that duplicates first Mb of OS_BASE at address 0;
  381. ; used for starting APs and for shutting down,
  382. ; where it is important to execute code in trivial-mapped pages.
  383. ; Returns eax = allocated physical page.
  384. proc create_trampoline_pgmap
  385. ; The only non-trivial moment:
  386. ; we need a linear address to fill information,
  387. ; but we don't need it outside of this function,
  388. ; so we're returning physical address.
  389. ; Therefore, allocate memory with kernel_alloc,
  390. ; this will allocate physical page and a linear address somewhere,
  391. ; and deallocate only linear address with free_kernel_space.
  392.         stdcall kernel_alloc, PAGE_SIZE
  393.         mov     edi, eax
  394.         mov     esi, master_tab
  395.         mov     ecx, PAGE_SIZE/4
  396.         rep movsd
  397.         mov     ecx, [master_tab + (OS_BASE shr 20)]
  398.         mov     [eax], ecx
  399.         mov     edi, eax
  400.         call    get_pg_addr
  401.         push    eax
  402.         stdcall free_kernel_space, edi
  403.         pop     eax
  404.         ret
  405. endp
  406.  
  407. align 4
  408. proc new_mem_resize stdcall, new_size:dword
  409.  
  410.         push    ebx
  411.         push    esi
  412.         push    edi
  413.  
  414.         mov     edx, [current_slot]
  415.         mov     ebx, [edx + APPDATA.process]
  416.  
  417.         cmp     [ebx + PROC.heap_base], 0
  418.         jne     .exit
  419.  
  420.         mov     edi, [new_size]
  421.         add     edi, PAGE_SIZE-1
  422.         and     edi, -PAGE_SIZE
  423.         mov     [new_size], edi
  424.  
  425.         mov     esi, [ebx + PROC.mem_used]
  426.         add     esi, PAGE_SIZE-1
  427.         and     esi, -PAGE_SIZE
  428.  
  429.         cmp     edi, esi
  430.         ja      .expand
  431.         je      .exit
  432.  
  433.         mov     ebx, edi
  434.         shr     edi, 12
  435.         shr     esi, 12
  436.  
  437.         mov     ecx, pg_data.mutex
  438.         call    mutex_lock
  439. @@:
  440.         mov     eax, [app_page_tabs + edi*4]
  441.         test    eax, 1
  442.         jz      .next
  443.  
  444.         mov     dword [app_page_tabs + edi*4], 0
  445.         invlpg  [ebx]
  446.         call    free_page
  447.  
  448. .next:
  449.         inc     edi
  450.         add     ebx, PAGE_SIZE
  451.         cmp     edi, esi
  452.         jb      @B
  453.  
  454.         mov     ecx, pg_data.mutex
  455.         call    mutex_unlock
  456.  
  457. .update_size:
  458.         mov     edx, [current_slot]
  459.         mov     ebx, [new_size]
  460.         mov     edx, [edx + APPDATA.process]
  461.         mov     [edx + PROC.mem_used], ebx
  462. .exit:
  463.         pop     edi
  464.         pop     esi
  465.         pop     ebx
  466.         xor     eax, eax
  467.         ret
  468.  
  469. .expand:
  470.  
  471.         mov     ecx, pg_data.mutex
  472.         call    mutex_lock
  473.  
  474.         xchg    esi, edi
  475.  
  476.         push    esi                   ;new size
  477.         push    edi                   ;old size
  478.  
  479.         add     edi, 0x3FFFFF
  480.         and     edi, not(0x3FFFFF)
  481.         add     esi, 0x3FFFFF
  482.         and     esi, not(0x3FFFFF)
  483.  
  484.         cmp     edi, esi
  485.         jae     .grow
  486.  @@:
  487.         call    alloc_page
  488.         test    eax, eax
  489.         jz      .exit_fail
  490.  
  491.         stdcall map_page_table, edi, eax
  492.  
  493.         push    edi
  494.         shr     edi, 10
  495.         add     edi, page_tabs
  496.         mov     ecx, 1024
  497.         xor     eax, eax
  498.         cld
  499.         rep stosd
  500.         pop     edi
  501.  
  502.         add     edi, 0x00400000
  503.         cmp     edi, esi
  504.         jb      @B
  505. .grow:
  506.         pop     edi                   ;old size
  507.         pop     ecx                   ;new size
  508.  
  509.         shr     edi, 10
  510.         shr     ecx, 10
  511.         sub     ecx, edi
  512.         shr     ecx, 2                ;pages count
  513.         mov     eax, 2
  514.  
  515.         add     edi, app_page_tabs
  516.         rep stosd
  517.  
  518.         mov     ecx, pg_data.mutex
  519.         call    mutex_unlock
  520.  
  521.         jmp     .update_size
  522.  
  523. .exit_fail:
  524.         mov     ecx, pg_data.mutex
  525.         call    mutex_unlock
  526.  
  527.         add     esp, 8
  528.         pop     edi
  529.         pop     esi
  530.         pop     ebx
  531.         xor     eax, eax
  532.         inc     eax
  533.         ret
  534. endp
  535.  
  536.  
  537. ; param
  538. ;  eax= linear address
  539. ;
  540. ; retval
  541. ;  eax= physical page address
  542.  
  543. align 4
  544. get_pg_addr:
  545.         sub     eax, OS_BASE
  546.         cmp     eax, 0x400000
  547.         jb      @f
  548.         shr     eax, 12
  549.         mov     eax, [page_tabs + (eax+(OS_BASE shr 12))*4]
  550. @@:
  551.         and     eax, -PAGE_SIZE
  552.         ret
  553.  
  554.  
  555. align 4
  556. ; Now it is called from core/sys32::exc_c (see stack frame there)
  557. proc page_fault_handler
  558.  
  559.     .err_addr   equ ebp-4
  560.  
  561.         push    ebx               ;save exception number (#PF)
  562.         mov     ebp, esp
  563.         mov     ebx, cr2
  564.         push    ebx               ;that is locals: .err_addr = cr2
  565.         inc     [pg_data.pages_faults]
  566.  
  567.         mov     eax, [pf_err_code]
  568.  
  569.         cmp     ebx, OS_BASE      ;ebx == .err_addr
  570.         jb      .user_space       ;page in application memory
  571.  
  572.         cmp     ebx, page_tabs
  573.         jb      .kernel_space     ;page in kernel memory
  574.  
  575.         cmp     ebx, kernel_tabs
  576.         jb      .alloc;.app_tabs  ;page tables of application ;
  577.                                   ;simply create one
  578. .core_tabs:
  579. .fail:  ;simply return to caller
  580.         mov     esp, ebp
  581.         pop     ebx               ;restore exception number (#PF)
  582.         ret
  583.  
  584. .user_space:
  585.         test    eax, PG_READ
  586.         jnz     .err_access       ;Page presents
  587.                                   ;Access error ?
  588.  
  589.         shr     ebx, 12
  590.         mov     ecx, ebx
  591.         shr     ecx, 10
  592.         mov     edx, [master_tab + ecx*4]
  593.         test    edx, PG_READ
  594.         jz      .fail             ;page table is not created
  595.                                   ;incorrect address in program
  596.  
  597.         mov     eax, [page_tabs + ebx*4]
  598.         test    eax, 2
  599.         jz      .fail             ;address is not reserved for usage. Error
  600.                                  
  601. .alloc:
  602.         call    alloc_page
  603.         test    eax, eax
  604.         jz      .fail
  605.  
  606.         stdcall map_page, [.err_addr], eax, PG_UWR
  607.  
  608.         mov     edi, [.err_addr]
  609.         and     edi, -PAGE_SIZE
  610.         mov     ecx, 1024
  611.         xor     eax, eax
  612.        ;cld     ;caller is duty for this
  613.         rep stosd
  614. .exit:  ;iret with repeat fault instruction
  615.         add     esp, 12;clear in stack: locals(.err_addr) + #PF + ret_to_caller
  616.         restore_ring3_context
  617.         iretd
  618.  
  619. .err_access:
  620. ; access denied? this may be a result of copy-on-write protection for DLL
  621. ; check list of HDLLs
  622.         and     ebx, -PAGE_SIZE
  623.         mov     eax, [current_process]
  624.         mov     eax, [eax + PROC.dlls_list_ptr]
  625.         test    eax, eax
  626.         jz      .fail
  627.         mov     esi, [eax + HDLL.fd]
  628. .scan_hdll:
  629.         cmp     esi, eax
  630.         jz      .fail
  631.         mov     edx, ebx
  632.         sub     edx, [esi + HDLL.base]
  633.         cmp     edx, [esi + HDLL.size]
  634.         jb      .fault_in_hdll
  635. .scan_hdll.next:
  636.         mov     esi, [esi + HDLL.fd]
  637.         jmp     .scan_hdll
  638. .fault_in_hdll:
  639. ; allocate new page, map it as rw and copy data
  640.         call    alloc_page
  641.         test    eax, eax
  642.         jz      .fail
  643.         stdcall map_page, ebx, eax, PG_UWR
  644.         mov     edi, ebx
  645.         mov     ecx, 1024
  646.         sub     ebx, [esi + HDLL.base]
  647.         mov     esi, [esi + HDLL.parent]
  648.         mov     esi, [esi + DLLDESCR.data]
  649.         add     esi, ebx
  650.         rep movsd
  651.         jmp     .exit
  652.  
  653. .kernel_space:
  654.         test    eax, PG_READ
  655.         jz      .fail   ;page does not present
  656.  
  657.         test    eax, 12 ;U/S (+below)
  658.         jnz     .fail   ;application requested kernel memory
  659.                        
  660.        ;test    eax, 8
  661.        ;jnz     .fail   ;the reserved bit is set in page tables. Added in P4/Xeon
  662.                        
  663.  
  664. ;an attempt to write to a protected kernel page
  665.  
  666.         cmp     ebx, tss._io_map_0
  667.         jb      .fail
  668.  
  669.         cmp     ebx, tss._io_map_0+8192
  670.         jae     .fail
  671.  
  672. ; io permission map
  673. ; copy-on-write protection
  674.  
  675.         call    alloc_page
  676.         test    eax, eax
  677.         jz      .fail
  678.  
  679.         push    eax
  680.         stdcall map_page, [.err_addr], eax, dword PG_SWR
  681.         pop     eax
  682.         mov     edi, [.err_addr]
  683.         and     edi, -PAGE_SIZE
  684.         lea     esi, [edi+(not tss._io_map_0)+1]; -tss._io_map_0
  685.  
  686.         mov     ebx, esi
  687.         shr     ebx, 12
  688.         mov     edx, [current_slot]
  689.         or      eax, PG_SWR
  690.         mov     [edx + APPDATA.io_map + ebx*4], eax
  691.  
  692.         add     esi, [default_io_map]
  693.         mov     ecx, PAGE_SIZE/4
  694.        ;cld     ;caller is duty for this
  695.         rep movsd
  696.         jmp     .exit
  697. endp
  698.  
  699. ; returns number of mapped bytes
  700. proc map_mem_ipc stdcall, lin_addr:dword,slot:dword,\
  701.                       ofs:dword,buf_size:dword,req_access:dword
  702.         locals
  703.              count   dd ?
  704.              process dd ?
  705.         endl
  706.  
  707.         mov     [count], 0
  708.         cmp     [buf_size], 0
  709.         jz      .exit
  710.  
  711.         mov     eax, [slot]
  712.         shl     eax, BSF sizeof.APPDATA
  713.         mov     eax, [SLOT_BASE + eax + APPDATA.process]
  714.         test    eax, eax
  715.         jz      .exit
  716.  
  717.         mov     [process], eax
  718.         mov     ebx, [ofs]
  719.         shr     ebx, 22
  720.         mov     eax, [eax + PROC.pdt_0 + ebx*4]                 ;get page table
  721.         mov     esi, [ipc_ptab]
  722.         and     eax, -PAGE_SIZE
  723.         jz      .exit
  724.         stdcall map_page, esi, eax, PG_SWR
  725. @@:
  726.         mov     edi, [lin_addr]
  727.         and     edi, -PAGE_SIZE
  728.         mov     ecx, [buf_size]
  729.         add     ecx, PAGE_SIZE-1
  730.         shr     ecx, 12
  731.         inc     ecx                  ; ???????????
  732.  
  733.         mov     edx, [ofs]
  734.         shr     edx, 12
  735.         and     edx, 0x3FF
  736. .map:
  737.         stdcall safe_map_page, [slot], [req_access], [ofs]
  738.         jnc     .exit
  739.         add     [count], PAGE_SIZE
  740.         add     [ofs], PAGE_SIZE
  741.         dec     ecx
  742.         jz      .exit
  743.  
  744.         add     edi, PAGE_SIZE
  745.         inc     edx
  746.         cmp     edx, 1024
  747.         jnz     .map
  748.  
  749.         inc     ebx
  750.         mov     eax, [process]
  751.         mov     eax, [eax + PROC.pdt_0 + ebx*4]
  752.         and     eax, -PAGE_SIZE
  753.         jz      .exit
  754.  
  755.         stdcall map_page, esi, eax, PG_SWR
  756.         xor     edx, edx
  757.         jmp     .map
  758. .exit:
  759.         mov     eax, [count]
  760.         ret
  761. endp
  762.  
  763. proc map_memEx stdcall, lin_addr:dword,slot:dword,\
  764.                         ofs:dword,buf_size:dword,req_access:dword
  765.         locals
  766.              count   dd ?
  767.              process dd ?
  768.         endl
  769.  
  770.         mov     [count], 0
  771.         cmp     [buf_size], 0
  772.         jz      .exit
  773.  
  774.         mov     eax, [slot]
  775.         shl     eax, BSF sizeof.APPDATA
  776.         mov     eax, [SLOT_BASE + eax + APPDATA.process]
  777.         test    eax, eax
  778.         jz      .exit
  779.  
  780.         mov     [process], eax
  781.         mov     ebx, [ofs]
  782.         shr     ebx, 22
  783.         mov     eax, [eax + PROC.pdt_0 + ebx*4]                 ;get page table
  784.         mov     esi, [proc_mem_tab]
  785.         and     eax, -PAGE_SIZE
  786.         jz      .exit
  787.         stdcall map_page, esi, eax, PG_SWR
  788. @@:
  789.         mov     edi, [lin_addr]
  790.         and     edi, -PAGE_SIZE
  791.         mov     ecx, [buf_size]
  792.         add     ecx, PAGE_SIZE-1
  793.         shr     ecx, 12
  794.         inc     ecx                  ; ???????????
  795.  
  796.         mov     edx, [ofs]
  797.         shr     edx, 12
  798.         and     edx, 0x3FF
  799. .map:
  800.         stdcall safe_map_page, [slot], [req_access], [ofs]
  801.         jnc     .exit
  802.         add     [count], PAGE_SIZE
  803.         add     [ofs], PAGE_SIZE
  804.         dec     ecx
  805.         jz      .exit
  806.  
  807.         add     edi, PAGE_SIZE
  808.         inc     edx
  809.         cmp     edx, 1024
  810.         jnz     .map
  811.  
  812.         inc     ebx
  813.         mov     eax, [process]
  814.         mov     eax, [eax + PROC.pdt_0 + ebx*4]
  815.         and     eax, -PAGE_SIZE
  816.         jz      .exit
  817.  
  818.         stdcall map_page, esi, eax, PG_SWR
  819.         xor     edx, edx
  820.         jmp     .map
  821. .exit:
  822.         mov     eax, [count]
  823.         ret
  824. endp
  825.  
  826. ; in: esi+edx*4 = pointer to page table entry
  827. ; in: [slot], [req_access], [ofs] on the stack
  828. ; in: edi = linear address to map
  829. ; out: CF cleared <=> failed
  830. ; destroys: only eax
  831. proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword
  832.         mov     eax, [esi + edx*4]
  833.         test    al, PG_READ
  834.         jz      .not_present
  835.         test    al, PG_WRITE
  836.         jz      .resolve_readonly
  837. ; normal case: writable page, just map with requested access
  838. .map:
  839.         stdcall map_page, edi, eax, [req_access]
  840.         stc
  841. .fail:
  842.         ret
  843. .not_present:
  844. ; check for alloc-on-demand page
  845.         test    al, 2
  846.         jz      .fail
  847. ; allocate new page, save it to source page table
  848.         push    ecx
  849.         call    alloc_page
  850.         pop     ecx
  851.         test    eax, eax
  852.         jz      .fail
  853.         or      al, PG_UWR
  854.         mov     [esi + edx*4], eax
  855.         jmp     .map
  856. .resolve_readonly:
  857. ; readonly page, probably copy-on-write
  858. ; check: readonly request of readonly page is ok
  859.         test    [req_access], PG_WRITE
  860.         jz      .map
  861. ; find control structure for this page
  862.         pushf
  863.         cli
  864.         cld
  865.         push    ebx ecx
  866.         mov     eax, [slot]
  867.         shl     eax, BSF sizeof.APPDATA
  868.         mov     eax, [SLOT_BASE + eax + APPDATA.process]
  869.         mov     eax, [eax + PROC.dlls_list_ptr]
  870.         test    eax, eax
  871.         jz      .no_hdll
  872.         mov     ecx, [eax + HDLL.fd]
  873. .scan_hdll:
  874.         cmp     ecx, eax
  875.         jz      .no_hdll
  876.         mov     ebx, [ofs]
  877.         and     ebx, -PAGE_SIZE
  878.         sub     ebx, [ecx + HDLL.base]
  879.         cmp     ebx, [ecx + HDLL.size]
  880.         jb      .hdll_found
  881.         mov     ecx, [ecx + HDLL.fd]
  882.         jmp     .scan_hdll
  883. .no_hdll:
  884.         pop     ecx ebx
  885.         popf
  886.         clc
  887.         ret
  888. .hdll_found:
  889. ; allocate page, save it in page table, map it, copy contents from base
  890.         mov     eax, [ecx + HDLL.parent]
  891.         add     ebx, [eax + DLLDESCR.data]
  892.         call    alloc_page
  893.         test    eax, eax
  894.         jz      .no_hdll
  895.         or      al, PG_UWR
  896.         mov     [esi + edx*4], eax
  897.         stdcall map_page, edi, eax, [req_access]
  898.         push    esi edi
  899.         mov     esi, ebx
  900.         mov     ecx, PAGE_SIZE/4
  901.         rep movsd
  902.         pop     edi esi
  903.         pop     ecx ebx
  904.         popf
  905.         stc
  906.         ret
  907. endp
  908.  
  909. sys_IPC:
  910. ;input:
  911. ;  ebx=1 - set ipc buffer area
  912. ;    ecx=address of buffer
  913. ;    edx=size of buffer
  914. ;  eax=2 - send message
  915. ;    ebx=PID
  916. ;    ecx=address of message
  917. ;    edx=size of message
  918.  
  919.         dec     ebx
  920.         jnz     @f
  921.  
  922.         mov     eax, [current_slot]
  923.         pushf
  924.         cli
  925.         mov     [eax + APPDATA.ipc_start], ecx    ;set fields in extended information area
  926.         mov     [eax + APPDATA.ipc_size], edx
  927.  
  928.         add     edx, ecx
  929.         add     edx, PAGE_SIZE-1
  930.         and     edx, -PAGE_SIZE
  931.  
  932. .touch:
  933.         mov     eax, [ecx]
  934.         add     ecx, PAGE_SIZE
  935.         cmp     ecx, edx
  936.         jb      .touch
  937.  
  938.         popf
  939.         mov     [esp + SYSCALL_STACK.eax], ebx   ;ebx=0
  940.         ret
  941.  
  942. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  943. ;2
  944. @@:
  945.         dec     ebx
  946.         jnz     @f
  947.  
  948.         stdcall sys_ipc_send, ecx, edx, esi
  949.         mov     [esp + SYSCALL_STACK.eax], eax
  950.         ret
  951. @@:
  952.         or      eax, -1
  953.         mov     [esp + SYSCALL_STACK.eax], eax
  954.         ret
  955.  
  956. proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
  957.            locals
  958.              dst_slot   dd ?
  959.              dst_offset dd ?
  960.              buf_size   dd ?
  961.              used_buf   dd ?
  962.            endl
  963.  
  964.         pushf
  965.         cli
  966.  
  967.         mov     eax, [PID]
  968.         call    pid_to_slot
  969.         test    eax, eax
  970.         jz      .no_pid
  971.  
  972.         mov     [dst_slot], eax
  973.         shl     eax, BSF sizeof.APPDATA
  974.         mov     edi, [SLOT_BASE + eax + APPDATA.ipc_start] ;is ipc area defined?
  975.         test    edi, edi
  976.         jz      .no_ipc_area
  977.  
  978.         mov     ebx, edi
  979.         and     ebx, 0xFFF
  980.         mov     [dst_offset], ebx
  981.  
  982.         mov     esi, [SLOT_BASE + eax + APPDATA.ipc_size]
  983.         mov     [buf_size], esi
  984.  
  985.         mov     ecx, [ipc_tmp]
  986.         cmp     esi, 0x40000-0x1000; size of [ipc_tmp] minus one page
  987.         jbe     @f
  988.         push    esi edi
  989.         add     esi, 0x1000
  990.         stdcall alloc_kernel_space, esi
  991.         mov     ecx, eax
  992.         pop     edi esi
  993. @@:
  994.         mov     [used_buf], ecx
  995.         stdcall map_mem_ipc, ecx, [dst_slot], \
  996.                 edi, esi, PG_SWR
  997.  
  998.         mov     edi, [dst_offset]
  999.         add     edi, [used_buf]
  1000.         cmp     dword [edi], 0
  1001.         jnz     .ipc_blocked          ;if dword [buffer]<>0 - ipc blocked now
  1002.  
  1003.         mov     edx, dword [edi+4]
  1004.         lea     ebx, [edx+8]
  1005.         add     ebx, [msg_size]
  1006.         cmp     ebx, [buf_size]
  1007.         ja      .buffer_overflow       ;esi<0 - not enough memory in buffer
  1008.  
  1009.         mov     dword [edi+4], ebx
  1010.         mov     eax, [current_slot]
  1011.         mov     eax, [eax + APPDATA.tid]        ;eax - our PID
  1012.         add     edi, edx
  1013.         mov     [edi], eax
  1014.         mov     ecx, [msg_size]
  1015.  
  1016.         mov     [edi+4], ecx
  1017.         add     edi, 8
  1018.         mov     esi, [msg_addr]
  1019.        ;    add esi, std_application_base_address
  1020.         cld
  1021.         rep movsb
  1022.  
  1023.         mov     ebx, [ipc_tmp]
  1024.         mov     edx, ebx
  1025.         shr     ebx, 12
  1026.         xor     eax, eax
  1027.         mov     [page_tabs + ebx*4], eax
  1028.         invlpg  [edx]
  1029.  
  1030.         mov     ebx, [ipc_pdir]
  1031.         mov     edx, ebx
  1032.         shr     ebx, 12
  1033.         xor     eax, eax
  1034.         mov     [page_tabs + ebx*4], eax
  1035.         invlpg  [edx]
  1036.  
  1037.         mov     ebx, [ipc_ptab]
  1038.         mov     edx, ebx
  1039.         shr     ebx, 12
  1040.         xor     eax, eax
  1041.         mov     [page_tabs + ebx*4], eax
  1042.         invlpg  [edx]
  1043.  
  1044.         mov     eax, [dst_slot]
  1045.         shl     eax, BSF sizeof.APPDATA
  1046.         or      [SLOT_BASE + eax + APPDATA.occurred_events], EVENT_IPC
  1047.         push    0
  1048.         jmp     .ret
  1049. .no_pid:
  1050.         popf
  1051.         mov     eax, 4
  1052.         ret
  1053. .no_ipc_area:
  1054.         popf
  1055.         xor     eax, eax
  1056.         inc     eax
  1057.         ret
  1058. .ipc_blocked:
  1059.         push    2
  1060.         jmp     .ret
  1061. .buffer_overflow:
  1062.         push    3
  1063. .ret:
  1064.         mov     eax, [used_buf]
  1065.         cmp     eax, [ipc_tmp]
  1066.         je      @f
  1067.         stdcall free_kernel_space, eax
  1068. @@:
  1069.         pop     eax
  1070.         popf
  1071.         ret
  1072. endp
  1073.  
  1074. align 4
  1075. sysfn_meminfo:
  1076.         cmp     ecx, OS_BASE
  1077.         jae     .fail
  1078.  
  1079.         mov     eax, [pg_data.pages_count]
  1080.         mov     [ecx], eax
  1081.         shl     eax, 12
  1082.         mov     [esp + SYSCALL_STACK.eax], eax
  1083.         mov     eax, [pg_data.pages_free]
  1084.         mov     [ecx + 4], eax
  1085.         mov     eax, [pg_data.pages_faults]
  1086.         mov     [ecx + 8], eax
  1087.         mov     eax, [heap_size]
  1088.         mov     [ecx + 12], eax
  1089.         mov     eax, [heap_free]
  1090.         mov     [ecx + 16], eax
  1091.         mov     eax, [heap_blocks]
  1092.         mov     [ecx + 20], eax
  1093.         mov     eax, [free_blocks]
  1094.         mov     [ecx + 24], eax
  1095.         ret
  1096. .fail:
  1097.         or      dword [esp + SYSCALL_STACK.eax], -1
  1098.         ret
  1099.  
  1100. align 4
  1101. f68:
  1102.         cmp     ebx, 4
  1103.         jbe     sys_sheduler
  1104.         cmp     ebx, 11
  1105.         jb      undefined_syscall
  1106.         cmp     ebx, 31
  1107.         ja      undefined_syscall
  1108.         xor     eax, eax
  1109.         jmp     dword [f68call + ebx*4-11*4]
  1110. .11:
  1111.         call    init_heap
  1112.         mov     [esp + SYSCALL_STACK.eax], eax
  1113.         ret
  1114. .12:
  1115.         stdcall user_alloc, ecx
  1116.         mov     [esp + SYSCALL_STACK.eax], eax
  1117.         ret
  1118. .13:
  1119.         stdcall user_free, ecx
  1120.         mov     [esp + SYSCALL_STACK.eax], eax
  1121.         ret
  1122. .14:
  1123.         cmp     ecx, OS_BASE
  1124.         jae     .fail
  1125.         mov     edi, ecx
  1126.         call    get_event_ex
  1127.         mov     [esp + SYSCALL_STACK.eax], eax
  1128.         ret
  1129. .16:
  1130.         test    ecx, ecx
  1131.         jz      .fail
  1132.         cmp     ecx, OS_BASE
  1133.         jae     .fail
  1134.         stdcall get_service, ecx
  1135.         mov     [esp + SYSCALL_STACK.eax], eax
  1136.         ret
  1137. .17:
  1138.         call    srv_handlerEx   ;ecx
  1139.         mov     [esp + SYSCALL_STACK.eax], eax
  1140.         ret
  1141. .18:
  1142.         mov     eax, edx
  1143. .19:
  1144.         stdcall is_string_userspace, ecx
  1145.         jnz     .fail
  1146.         stdcall load_library, ecx, eax
  1147.         mov     [esp + SYSCALL_STACK.eax], eax
  1148.         ret
  1149. .20:
  1150.         mov     eax, edx
  1151.         mov     ebx, ecx
  1152.         call    user_realloc            ;in: eax = pointer, ebx = new size
  1153.         mov     [esp + SYSCALL_STACK.eax], eax
  1154.         ret
  1155. .21:
  1156.         cmp     ecx, OS_BASE
  1157.         jae     .fail
  1158.         cmp     edx, OS_BASE
  1159.         jae     .fail
  1160.         stdcall load_pe_driver, ecx, edx
  1161.         mov     [esp + SYSCALL_STACK.eax], eax
  1162.         ret
  1163. .22:
  1164.         cmp     ecx, OS_BASE
  1165.         jae     .fail
  1166.         stdcall shmem_open, ecx, edx, esi
  1167.         mov     [esp + SYSCALL_STACK.edx], edx
  1168.         mov     [esp + SYSCALL_STACK.eax], eax
  1169.         ret
  1170. .23:
  1171.         cmp     ecx, OS_BASE
  1172.         jae     .fail
  1173.         stdcall shmem_close, ecx
  1174.         mov     [esp + SYSCALL_STACK.eax], eax
  1175.         ret
  1176. .24:
  1177.         mov     eax, [current_slot]
  1178.         xchg    ecx, [eax + APPDATA.exc_handler]
  1179.         xchg    edx, [eax + APPDATA.except_mask]
  1180.         xchg    esi, [eax + APPDATA.exc_reserve_stack]
  1181.         mov     [esp + SYSCALL_STACK.ebx], edx
  1182.         mov     [esp + SYSCALL_STACK.eax], ecx
  1183.         ret
  1184. .25:
  1185.         cmp     ecx, 32
  1186.         jae     .fail
  1187.         mov     eax, [current_slot]
  1188.         btr     [eax + APPDATA.except_mask], ecx
  1189.         setc    byte[esp + SYSCALL_STACK.eax]
  1190.         jecxz   @f
  1191.         bts     [eax + APPDATA.except_mask], ecx
  1192. @@:
  1193.         ret
  1194. .26:
  1195.         stdcall user_unmap, ecx, edx, esi
  1196.         mov     [esp + SYSCALL_STACK.eax], eax
  1197.         ret
  1198. .27:
  1199.         cmp     ecx, OS_BASE
  1200.         jae     .fail
  1201.         stdcall load_file_umode, ecx
  1202.         mov     [esp + SYSCALL_STACK.edx], edx
  1203.         mov     [esp + SYSCALL_STACK.eax], eax
  1204.         ret
  1205. .28:
  1206.         cmp     ecx, OS_BASE
  1207.         jae     .fail
  1208.         push    ecx edx
  1209.         stdcall kernel_alloc, maxPathLength
  1210.         mov     edi, eax
  1211.         pop     eax esi
  1212.         push    edi
  1213.         call    getFullPath
  1214.         pop     ebp
  1215.         test    eax, eax
  1216.         jz      @f
  1217.         stdcall load_file_umode, ebp
  1218.         mov     [esp + SYSCALL_STACK.edx], edx
  1219. @@:
  1220.         mov     [esp + SYSCALL_STACK.eax], eax
  1221.         stdcall kernel_free, ebp
  1222.         ret
  1223.  
  1224. .29:
  1225.         stdcall user_ring, ecx
  1226.         mov     [esp + SYSCALL_STACK.eax], eax
  1227.         ret
  1228.  
  1229. ;  unload driver
  1230. .30:                         ; ecx = handl driver edx = cmdline
  1231.         mov     eax, -1
  1232.         cmp     edx, OS_BASE
  1233.         jae     .fail
  1234.         cmp     ecx, OS_BASE
  1235.         jbe     .fail
  1236.         cmp     [ecx+SRV.magic], ' SRV'
  1237.         jne     .fail
  1238.         cmp     [ecx+SRV.size], sizeof.SRV
  1239.         jne     .fail
  1240.  
  1241.         mov     eax, [ecx + SRV.entry]
  1242.         test    eax, eax
  1243.         jz      .fail
  1244.         push    ecx    ;save handl
  1245.  
  1246.         push    edx         ;cmdline
  1247.         push    DRV_EXIT
  1248.         call    eax   ;the result is not checked
  1249.         lea     esp, [esp+8]
  1250.         push    ecx
  1251.  
  1252.         mov     ebx, [ecx + SRV.base]
  1253.         mov     eax, -2 ;error free RAM
  1254.         test    ebx, ebx
  1255.         jz      .fail
  1256.         stdcall kernel_free, ebx ;del driver
  1257.  
  1258.         mov     eax, [ecx + SRV.fd]
  1259.         mov     edx, [ecx + SRV.bk]
  1260.         mov     [edx + SRV.fd], eax
  1261.         mov     [eax + SRV.bk], edx
  1262.         stdcall free, ecx
  1263.         ;dec     [count_services]
  1264.  
  1265.         mov     [esp + SYSCALL_STACK.eax], eax
  1266.         ret
  1267. .31:    ; get list service
  1268.         test    ecx, ecx
  1269.         jz      .fail   ; get count
  1270.         dec     ecx
  1271.         jnz     @f    ;1 - get pointer first and last  structure
  1272.  
  1273.         mov     ebx, [srv.fd]
  1274.         mov     ecx, [srv.bk]
  1275.         mov     [esp + SYSCALL_STACK.ebx], ebx  ;fd
  1276.         mov     [esp + SYSCALL_STACK.ecx], ecx  ;bk
  1277.         mov     [esp + SYSCALL_STACK.eax], 0
  1278.         ret
  1279. @@:
  1280.         dec     ecx
  1281.         jnz     .fail  ; 2 - get info for SRV structure
  1282.  
  1283.         mov     eax, -1
  1284.         cmp     edx, OS_BASE    ; edx = pointer on structure
  1285.         jbe     .fail
  1286.         stdcall is_region_userspace, edi, 40 ;16+4*6=40 <-max size buffer
  1287.         jnz     .fail                        ; edi = pointer on buffer
  1288.         cmp     [edx + SRV.magic], ' SRV'
  1289.         jne     .fail
  1290.         cmp     [edx + SRV.size], sizeof.SRV
  1291.         jne     .fail
  1292.  
  1293.         mov     esi, edx
  1294.         movsd     ; name service 16 byte
  1295.         movsd
  1296.         movsd
  1297.         movsd
  1298.         lea     esi, [edx+SRV.fd]
  1299.         movsd   ; SRV.fd
  1300.         movsd   ; SRV.bk
  1301.         movsd   ; SRV.base
  1302.         movsd   ; SRV.entry
  1303.         movsd   ; SRV.srv_proc
  1304.         ;movsd   ; SRV.srv_proc_ex
  1305.  
  1306.         xor     eax, eax
  1307. .fail:
  1308.         mov     [esp + SYSCALL_STACK.eax], eax
  1309.         ret
  1310.  
  1311. align 4
  1312. f68call:   ; keep this table closer to main code
  1313.  
  1314.            dd f68.11   ; init_heap
  1315.            dd f68.12   ; user_alloc
  1316.            dd f68.13   ; user_free
  1317.            dd f68.14   ; get_event_ex
  1318.            dd f68.fail ; moved to f68.24
  1319.            dd f68.16   ; get_service
  1320.            dd f68.17   ; call_service
  1321.            dd f68.18   ; loadLibUnicode
  1322.            dd f68.19   ; load_dll
  1323.            dd f68.20   ; user_realloc
  1324.            dd f68.21   ; load_driver
  1325.            dd f68.22   ; shmem_open
  1326.            dd f68.23   ; shmem_close
  1327.            dd f68.24   ; set exception handler
  1328.            dd f68.25   ; unmask exception
  1329.            dd f68.26   ; user_unmap
  1330.            dd f68.27   ; load_file_umode
  1331.            dd f68.28   ; loadFileUnicode
  1332.            dd f68.29   ; user_ring
  1333.            dd f68.30   ; unload_driver
  1334.            dd f68.31   ; get_driver_info
  1335.  
  1336. align 4
  1337. proc load_pe_driver stdcall, file:dword, cmdline:dword
  1338.         push    esi
  1339.  
  1340.         stdcall load_PE, [file]
  1341.         test    eax, eax
  1342.         jz      .fail
  1343.  
  1344.         mov     esi, eax
  1345.         push    ebx  ;  base addres driver
  1346.         push    [cmdline]
  1347.         push    DRV_ENTRY
  1348.         call    eax
  1349.         pop     ecx
  1350.         pop     ecx
  1351.         pop     ebx
  1352.         test    eax, eax
  1353.         jz      .fail_init
  1354.  
  1355.         mov     [eax + SRV.base], ebx
  1356.         mov     [eax + SRV.entry], esi
  1357.         pop     esi
  1358.         ret
  1359. .fail_init:
  1360.         stdcall kernel_free, ebx  ;clear memory driver
  1361. .fail:
  1362.         xor     eax, eax
  1363.         pop     esi
  1364.         ret
  1365. endp
  1366.  
  1367. align 4
  1368. proc create_ring_buffer stdcall, size:dword, flags:dword
  1369.            locals
  1370.              buf_ptr  dd ?
  1371.            endl
  1372.  
  1373.         mov     eax, [size]
  1374.         test    eax, eax
  1375.         jz      .fail
  1376.  
  1377.         add     eax, eax
  1378.         stdcall alloc_kernel_space, eax
  1379.         test    eax, eax
  1380.         jz      .fail
  1381.  
  1382.         push    ebx
  1383.  
  1384.         mov     [buf_ptr], eax
  1385.  
  1386.         mov     ebx, [size]
  1387.         shr     ebx, 12
  1388.         push    ebx
  1389.  
  1390.         stdcall alloc_pages, ebx
  1391.         pop     ecx
  1392.  
  1393.         test    eax, eax
  1394.         jz      .mm_fail
  1395.  
  1396.         push    edi
  1397.  
  1398.         or      eax, [flags]
  1399.         mov     edi, [buf_ptr]
  1400.         mov     ebx, [buf_ptr]
  1401.         mov     edx, ecx
  1402.         shl     edx, 2
  1403.         shr     edi, 10
  1404. @@:
  1405.         mov     [page_tabs + edi], eax
  1406.         mov     [page_tabs + edi + edx], eax
  1407.         invlpg  [ebx]
  1408.         invlpg  [ebx+0x10000]
  1409.         add     eax, 0x1000
  1410.         add     ebx, 0x1000
  1411.         add     edi, 4
  1412.         dec     ecx
  1413.         jnz     @B
  1414.  
  1415.         mov     eax, [buf_ptr]
  1416.         pop     edi
  1417.         pop     ebx
  1418.         ret
  1419. .mm_fail:
  1420.         stdcall free_kernel_space, [buf_ptr]
  1421.         xor     eax, eax
  1422.         pop     ebx
  1423. .fail:
  1424.         ret
  1425. endp
  1426.  
  1427.  
  1428. align 4
  1429. proc print_mem
  1430.         mov     edi, BOOT.memmap_blocks
  1431.         mov     ecx, [edi-4]
  1432.         test    ecx, ecx
  1433.         jz      .done
  1434.  
  1435. @@:
  1436.         mov     eax, [edi]
  1437.         mov     edx, [edi+4]
  1438.         add     eax, [edi+8]
  1439.         adc     edx, [edi+12]
  1440.  
  1441.         DEBUGF  1, "K : E820 %x%x - %x%x type %d\n", \
  1442.                     [edi+4], [edi],\
  1443.                     edx, eax, [edi+16]
  1444.         add     edi, 20
  1445.         dec     ecx
  1446.         jnz     @b
  1447. .done:
  1448.         ret
  1449. endp
  1450.