Subversion Repositories Kolibri OS

Rev

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

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