Subversion Repositories Kolibri OS

Rev

Rev 5032 | Rev 5356 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 5057 $
  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.         and     eax, not 0xFFF
  131.         or      eax, [esp+16]              ; flags
  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, 4095
  177.         and     eax, -4096
  178.         mov     ecx, [base]
  179.         and     ecx, -4096
  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, 0x1000
  189.         mov     ebx, eax
  190.         mov     ecx, [size]
  191.         mov     edx, [base]
  192.         shr     eax, 12
  193.         shr     ecx, 12
  194.         and     edx, -4096
  195.         or      edx, [flags]
  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, 4095
  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.         mov     edi, ebx
  233.         shr     edi, 12
  234.         lea     edi, [page_tabs+edi*4]
  235. @@:
  236.         stosd
  237.         invlpg  [ebx]
  238.         add     eax, 0x1000
  239.         add     ebx, 0x1000
  240.         loop    @B
  241.  
  242.         pop     edi
  243.  
  244.         mov     ecx, pg_data.mutex
  245.         call    mutex_unlock
  246. .fail:
  247.         ret
  248.  
  249.  
  250. ; param
  251. ;  eax= base
  252. ;  ecx= count
  253.  
  254. align 4
  255. release_pages:
  256.  
  257.         push    ebp
  258.         push    esi
  259.         push    edi
  260.         push    ebx
  261.  
  262.         mov     esi, eax
  263.         mov     edi, eax
  264.  
  265.         shr     esi, 12
  266.         lea     esi, [page_tabs+esi*4]
  267.  
  268.         push    ecx
  269.         mov     ecx, pg_data.mutex
  270.         call    mutex_lock
  271.         pop     ecx
  272.  
  273.         mov     ebp, [pg_data.pages_free]
  274.         mov     ebx, [page_start]
  275.         mov     edx, sys_pgmap
  276. @@:
  277.         xor     eax, eax
  278.         xchg    eax, [esi]
  279.         invlpg  [edi]
  280.  
  281.         test    eax, 1
  282.         jz      .next
  283.  
  284.         shr     eax, 12
  285.         bts     [edx], eax
  286.         cmc
  287.         adc     ebp, 0
  288.         shr     eax, 3
  289.         and     eax, -4
  290.         add     eax, edx
  291.         cmp     eax, ebx
  292.         jae     .next
  293.  
  294.         mov     ebx, eax
  295. .next:
  296.         add     edi, 0x1000
  297.         add     esi, 4
  298.         loop    @B
  299.  
  300.         mov     [pg_data.pages_free], ebp
  301.         mov     ecx, pg_data.mutex
  302.         call    mutex_unlock
  303.  
  304.         pop     ebx
  305.         pop     edi
  306.         pop     esi
  307.         pop     ebp
  308.         ret
  309.  
  310. ; param
  311. ;  eax= base
  312. ;  ecx= count
  313.  
  314. align 4
  315. unmap_pages:
  316.  
  317.         push    edi
  318.  
  319.         mov     edi, eax
  320.         mov     edx, eax
  321.  
  322.         shr     edi, 10
  323.         add     edi, page_tabs
  324.  
  325.         xor     eax, eax
  326. @@:
  327.         stosd
  328.         invlpg  [edx]
  329.         add     edx, 0x1000
  330.         loop    @b
  331.  
  332.         pop     edi
  333.         ret
  334.  
  335.  
  336. align 4
  337. proc map_page_table stdcall, lin_addr:dword, phis_addr:dword
  338.         push    ebx
  339.         mov     ebx, [lin_addr]
  340.         shr     ebx, 22
  341.         mov     eax, [phis_addr]
  342.         and     eax, not 0xFFF
  343.         or      eax, PG_UW        ;+PG_NOCACHE
  344.         mov     dword [master_tab+ebx*4], eax
  345.         mov     eax, [lin_addr]
  346.         shr     eax, 10
  347.         add     eax, page_tabs
  348.         invlpg  [eax]
  349.         pop     ebx
  350.         ret
  351. endp
  352.  
  353. uglobal
  354. sb16_buffer_allocated db 0
  355. endg
  356.  
  357. ; Allocates [.size] bytes so that the target memory block
  358. ; is inside one 64K page for 24-bit DMA controller,
  359. ; that is, somewhere between 00xx0000h and 00xxFFFFh.
  360. proc alloc_dma24
  361. ; Implementation note.
  362. ; The only user of that function is SB16 driver,
  363. ; so just return a statically allocated buffer.
  364. virtual at esp
  365.                 dd      ? ; return address
  366. .size           dd      ?
  367. end virtual
  368.         cmp     [sb16_buffer_allocated], 0
  369.         jnz     .fail
  370.         inc     [sb16_buffer_allocated]
  371.         mov     eax, SB16Buffer
  372.         ret     4
  373. .fail:
  374.         xor     eax, eax
  375.         ret     4
  376. endp
  377.  
  378. ; Allocates a physical page for master page table
  379. ; that duplicates first Mb of OS_BASE at address 0;
  380. ; used for starting APs and for shutting down,
  381. ; where it is important to execute code in trivial-mapped pages.
  382. ; Returns eax = allocated physical page.
  383. proc create_trampoline_pgmap
  384. ; The only non-trivial moment:
  385. ; we need a linear address to fill information,
  386. ; but we don't need it outside of this function,
  387. ; so we're returning physical address.
  388. ; Therefore, allocate memory with kernel_alloc,
  389. ; this will allocate physical page and a linear address somewhere,
  390. ; and deallocate only linear address with free_kernel_space.
  391.         stdcall kernel_alloc, 0x1000
  392.         mov     edi, eax
  393.         mov     esi, master_tab
  394.         mov     ecx, 1024
  395.         rep movsd
  396.         mov     ecx, [master_tab+(OS_BASE shr 20)]
  397.         mov     [eax], ecx
  398.         mov     edi, eax
  399.         call    get_pg_addr
  400.         push    eax
  401.         stdcall free_kernel_space, edi
  402.         pop     eax
  403.         ret
  404. endp
  405.  
  406. align 4
  407. proc init_LFB
  408.            locals
  409.              pg_count dd ?
  410.            endl
  411.  
  412.         cmp     dword [LFBAddress], -1
  413.         jne     @f
  414.         mov     [BOOT_VARS+BOOT_MTRR], byte 2
  415. ; max VGA=640*480*4=1228800 bytes
  416. ; + 32*640*4=81920 bytes for mouse pointer
  417.         stdcall alloc_pages, ((1228800+81920)/4096)
  418.  
  419.         push    eax
  420.         call    alloc_page
  421.         stdcall map_page_table, LFB_BASE, eax
  422.         pop     eax
  423.         or      eax, PG_UW
  424.         mov     ebx, LFB_BASE
  425. ; max VGA=640*480*4=1228800 bytes
  426. ; + 32*640*4=81920 bytes for mouse pointer
  427.         mov     ecx, (1228800+81920)/4096
  428.         call    commit_pages
  429.         mov     [LFBAddress], dword LFB_BASE
  430.         ret
  431. @@:
  432.         test    [SCR_MODE], word 0100000000000000b
  433.         jnz     @f
  434.         mov     [BOOT_VARS+BOOT_MTRR], byte 2
  435.         ret
  436. @@:
  437.         call    init_mtrr
  438.  
  439.         mov     edx, LFB_BASE
  440.         mov     esi, [LFBAddress]
  441.         mov     edi, 0x00C00000
  442.         mov     dword [exp_lfb+4], edx
  443.  
  444.         shr     edi, 12
  445.         mov     [pg_count], edi
  446.         shr     edi, 10
  447.  
  448.         bt      [cpu_caps], CAPS_PSE
  449.         jnc     .map_page_tables
  450.         or      esi, PG_LARGE+PG_UW
  451.         mov     edx, sys_pgdir+(LFB_BASE shr 20)
  452. @@:
  453.         mov     [edx], esi
  454.         add     edx, 4
  455.         add     esi, 0x00400000
  456.         dec     edi
  457.         jnz     @B
  458.  
  459.         bt      [cpu_caps], CAPS_PGE
  460.         jnc     @F
  461.         or      dword [sys_pgdir+(LFB_BASE shr 20)], PG_GLOBAL
  462. @@:
  463.         mov     dword [LFBAddress], LFB_BASE
  464.         mov     eax, cr3      ;flush TLB
  465.         mov     cr3, eax
  466.         ret
  467.  
  468. .map_page_tables:
  469.  
  470. @@:
  471.         call    alloc_page
  472.         stdcall map_page_table, edx, eax
  473.         add     edx, 0x00400000
  474.         dec     edi
  475.         jnz     @B
  476.  
  477.         mov     eax, [LFBAddress]
  478.         mov     edi, page_tabs + (LFB_BASE shr 10)
  479.         or      eax, PG_UW
  480.         mov     ecx, [pg_count]
  481.         cld
  482. @@:
  483.         stosd
  484.         add     eax, 0x1000
  485.         dec     ecx
  486.         jnz     @B
  487.  
  488.         mov     dword [LFBAddress], LFB_BASE
  489.         mov     eax, cr3      ;flush TLB
  490.         mov     cr3, eax
  491.  
  492.         ret
  493. endp
  494.  
  495. align 4
  496. proc new_mem_resize stdcall, new_size:dword
  497.  
  498.         push    ebx
  499.         push    esi
  500.         push    edi
  501.  
  502.         mov     edx, [current_slot]
  503.         cmp     [edx+APPDATA.heap_base], 0
  504.         jne     .exit
  505.  
  506.         mov     edi, [new_size]
  507.         add     edi, 4095
  508.         and     edi, not 4095
  509.         mov     [new_size], edi
  510.  
  511.         mov     esi, [edx+APPDATA.mem_size]
  512.         add     esi, 4095
  513.         and     esi, not 4095
  514.  
  515.         cmp     edi, esi
  516.         ja      .expand
  517.         je      .exit
  518.  
  519.         mov     ebx, edi
  520.         shr     edi, 12
  521.         shr     esi, 12
  522.  
  523.         mov     ecx, pg_data.mutex
  524.         call    mutex_lock
  525. @@:
  526.         mov     eax, [app_page_tabs+edi*4]
  527.         test    eax, 1
  528.         jz      .next
  529.  
  530.         mov     dword [app_page_tabs+edi*4], 0
  531.         invlpg  [ebx]
  532.         call    free_page
  533.  
  534. .next:
  535.         inc     edi
  536.         add     ebx, 0x1000
  537.         cmp     edi, esi
  538.         jb      @B
  539.  
  540.         mov     ecx, pg_data.mutex
  541.         call    mutex_unlock
  542.  
  543. .update_size:
  544.         mov     edx, [current_slot]
  545.         mov     ebx, [new_size]
  546.         call    update_mem_size
  547. .exit:
  548.         pop     edi
  549.         pop     esi
  550.         pop     ebx
  551.         xor     eax, eax
  552.         ret
  553.  
  554. .expand:
  555.  
  556.         mov     ecx, pg_data.mutex
  557.         call    mutex_lock
  558.  
  559.         xchg    esi, edi
  560.  
  561.         push    esi                   ;new size
  562.         push    edi                   ;old size
  563.  
  564.         add     edi, 0x3FFFFF
  565.         and     edi, not(0x3FFFFF)
  566.         add     esi, 0x3FFFFF
  567.         and     esi, not(0x3FFFFF)
  568.  
  569.         cmp     edi, esi
  570.         jae     .grow
  571.  @@:
  572.         call    alloc_page
  573.         test    eax, eax
  574.         jz      .exit_fail
  575.  
  576.         stdcall map_page_table, edi, eax
  577.  
  578.         push    edi
  579.         shr     edi, 10
  580.         add     edi, page_tabs
  581.         mov     ecx, 1024
  582.         xor     eax, eax
  583.         cld
  584.         rep stosd
  585.         pop     edi
  586.  
  587.         add     edi, 0x00400000
  588.         cmp     edi, esi
  589.         jb      @B
  590. .grow:
  591.         pop     edi                   ;old size
  592.         pop     ecx                   ;new size
  593.  
  594.         shr     edi, 10
  595.         shr     ecx, 10
  596.         sub     ecx, edi
  597.         shr     ecx, 2                ;pages count
  598.         mov     eax, 2
  599.  
  600.         add     edi, app_page_tabs
  601.         rep stosd
  602.  
  603.         mov     ecx, pg_data.mutex
  604.         call    mutex_unlock
  605.  
  606.         jmp     .update_size
  607.  
  608. .exit_fail:
  609.         mov     ecx, pg_data.mutex
  610.         call    mutex_unlock
  611.  
  612.         add     esp, 8
  613.         pop     edi
  614.         pop     esi
  615.         pop     ebx
  616.         xor     eax, eax
  617.         inc     eax
  618.         ret
  619. endp
  620.  
  621.  
  622. align 4
  623. update_mem_size:
  624. ; in: edx = slot base
  625. ;     ebx = new memory size
  626. ; destroys eax,ecx,edx
  627.  
  628.         mov     [APPDATA.mem_size+edx], ebx
  629. ;search threads and update
  630. ;application memory size infomation
  631.         mov     ecx, [APPDATA.dir_table+edx]
  632.         mov     eax, 2
  633.  
  634. .search_threads:
  635. ;eax = current slot
  636. ;ebx = new memory size
  637. ;ecx = page directory
  638.         cmp     eax, [TASK_COUNT]
  639.         jg      .search_threads_end
  640.         mov     edx, eax
  641.         shl     edx, 5
  642.         cmp     word [CURRENT_TASK+edx+TASKDATA.state], 9  ;if slot empty?
  643.         jz      .search_threads_next
  644.         shl     edx, 3
  645.         cmp     [SLOT_BASE+edx+APPDATA.dir_table], ecx      ;if it is our thread?
  646.         jnz     .search_threads_next
  647.         mov     [SLOT_BASE+edx+APPDATA.mem_size], ebx      ;update memory size
  648. .search_threads_next:
  649.         inc     eax
  650.         jmp     .search_threads
  651. .search_threads_end:
  652.         ret
  653.  
  654. ; param
  655. ;  eax= linear address
  656. ;
  657. ; retval
  658. ;  eax= phisical page address
  659.  
  660. align 4
  661. get_pg_addr:
  662.         sub     eax, OS_BASE
  663.         cmp     eax, 0x400000
  664.         jb      @f
  665.         shr     eax, 12
  666.         mov     eax, [page_tabs+(eax+(OS_BASE shr 12))*4]
  667. @@:
  668.         and     eax, 0xFFFFF000
  669.         ret
  670.  
  671.  
  672. align 4
  673. ; Now it is called from core/sys32::exc_c (see stack frame there)
  674. proc page_fault_handler
  675.  
  676.     .err_addr   equ ebp-4
  677.  
  678.         push    ebx               ;save exception number (#PF)
  679.         mov     ebp, esp
  680.         mov     ebx, cr2
  681.         push    ebx               ;that is locals: .err_addr = cr2
  682.         inc     [pg_data.pages_faults]
  683.  
  684.         mov     eax, [pf_err_code]
  685.  
  686.         cmp     ebx, OS_BASE      ;ebx == .err_addr
  687.         jb      .user_space       ;страница в памяти приложения ;
  688.  
  689.         cmp     ebx, page_tabs
  690.         jb      .kernel_space     ;страница в памяти ядра
  691.  
  692.         cmp     ebx, kernel_tabs
  693.         jb      .alloc;.app_tabs  ;таблицы страниц приложения ;
  694.                                   ;просто создадим одну
  695. if 0 ;пока это просто лишнее
  696.         cmp     ebx, LFB_BASE
  697.         jb      .core_tabs        ;таблицы страниц ядра
  698.                                   ;Ошибка
  699.   .lfb:
  700.                                   ;область LFB
  701.                                   ;Ошибка
  702.         jmp     .fail
  703. end if
  704. .core_tabs:
  705. .fail:  ;simply return to caller
  706.         mov     esp, ebp
  707.         pop     ebx               ;restore exception number (#PF)
  708.         ret
  709.  
  710. ;        xchg bx, bx
  711. ;        add     esp,12 ;clear in stack: locals(.err_addr) + #PF + ret_to_caller
  712. ;        restore_ring3_context
  713. ;        iretd
  714.  
  715. .user_space:
  716.         test    eax, PG_MAP
  717.         jnz     .err_access       ;Страница присутствует
  718.                                   ;Ошибка доступа ?
  719.  
  720.         shr     ebx, 12
  721.         mov     ecx, ebx
  722.         shr     ecx, 10
  723.         mov     edx, [master_tab+ecx*4]
  724.         test    edx, PG_MAP
  725.         jz      .fail             ;таблица страниц не создана
  726.                                   ;неверный адрес в программе
  727.  
  728.         mov     eax, [page_tabs+ebx*4]
  729.         test    eax, 2
  730.         jz      .fail             ;адрес не зарезервирован для ;
  731.                                   ;использования. Ошибка
  732. .alloc:
  733.         call    alloc_page
  734.         test    eax, eax
  735.         jz      .fail
  736.  
  737.         stdcall map_page, [.err_addr], eax, PG_UW
  738.  
  739.         mov     edi, [.err_addr]
  740.         and     edi, 0xFFFFF000
  741.         mov     ecx, 1024
  742.         xor     eax, eax
  743.        ;cld     ;caller is duty for this
  744.         rep stosd
  745. .exit:  ;iret with repeat fault instruction
  746.         add     esp, 12;clear in stack: locals(.err_addr) + #PF + ret_to_caller
  747.         restore_ring3_context
  748.         iretd
  749.  
  750. .err_access:
  751. ; access denied? this may be a result of copy-on-write protection for DLL
  752. ; check list of HDLLs
  753.         and     ebx, not 0xFFF
  754.         mov     eax, [CURRENT_TASK]
  755.         shl     eax, 8
  756.         mov     eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr]
  757.         test    eax, eax
  758.         jz      .fail
  759.         mov     esi, [eax+HDLL.fd]
  760. .scan_hdll:
  761.         cmp     esi, eax
  762.         jz      .fail
  763.         mov     edx, ebx
  764.         sub     edx, [esi+HDLL.base]
  765.         cmp     edx, [esi+HDLL.size]
  766.         jb      .fault_in_hdll
  767. .scan_hdll.next:
  768.         mov     esi, [esi+HDLL.fd]
  769.         jmp     .scan_hdll
  770. .fault_in_hdll:
  771. ; allocate new page, map it as rw and copy data
  772.         call    alloc_page
  773.         test    eax, eax
  774.         jz      .fail
  775.         stdcall map_page, ebx, eax, PG_UW
  776.         mov     edi, ebx
  777.         mov     ecx, 1024
  778.         sub     ebx, [esi+HDLL.base]
  779.         mov     esi, [esi+HDLL.parent]
  780.         mov     esi, [esi+DLLDESCR.data]
  781.         add     esi, ebx
  782.         rep movsd
  783.         jmp     .exit
  784.  
  785. .kernel_space:
  786.         test    eax, PG_MAP
  787.         jz      .fail   ;страница не присутствует
  788.  
  789.         test    eax, 12 ;U/S (+below)
  790.         jnz     .fail   ;приложение обратилось к памяти
  791.                         ;ядра
  792.        ;test    eax, 8
  793.        ;jnz     .fail   ;установлен зарезервированный бит
  794.                         ;в таблицах страниц. добавлено в P4/Xeon
  795.  
  796. ;попытка записи в защищённую страницу ядра
  797.  
  798.         cmp     ebx, tss._io_map_0
  799.         jb      .fail
  800.  
  801.         cmp     ebx, tss._io_map_0+8192
  802.         jae     .fail
  803.  
  804. ; io permission map
  805. ; copy-on-write protection
  806.  
  807.         call    alloc_page
  808.         test    eax, eax
  809.         jz      .fail
  810.  
  811.         push    eax
  812.         stdcall map_page, [.err_addr], eax, dword PG_SW
  813.         pop     eax
  814.         mov     edi, [.err_addr]
  815.         and     edi, -4096
  816.         lea     esi, [edi+(not tss._io_map_0)+1]; -tss._io_map_0
  817.  
  818.         mov     ebx, esi
  819.         shr     ebx, 12
  820.         mov     edx, [current_slot]
  821.         or      eax, PG_SW
  822.         mov     [edx+APPDATA.io_map+ebx*4], eax
  823.  
  824.         add     esi, [default_io_map]
  825.         mov     ecx, 4096/4
  826.        ;cld     ;caller is duty for this
  827.         rep movsd
  828.         jmp     .exit
  829. endp
  830.  
  831. ; returns number of mapped bytes
  832. proc map_mem stdcall, lin_addr:dword,slot:dword,\
  833.                       ofs:dword,buf_size:dword,req_access:dword
  834.         push    0 ; initialize number of mapped bytes
  835.  
  836.         cmp     [buf_size], 0
  837.         jz      .exit
  838.  
  839.         mov     eax, [slot]
  840.         shl     eax, 8
  841.         mov     eax, [SLOT_BASE+eax+APPDATA.dir_table]
  842.         and     eax, 0xFFFFF000
  843.  
  844.         stdcall map_page, [ipc_pdir], eax, PG_UW
  845.         mov     ebx, [ofs]
  846.         shr     ebx, 22
  847.         mov     esi, [ipc_pdir]
  848.         mov     edi, [ipc_ptab]
  849.         mov     eax, [esi+ebx*4]
  850.         and     eax, 0xFFFFF000
  851.         jz      .exit
  852.         stdcall map_page, edi, eax, PG_UW
  853. ;           inc ebx
  854. ;           add edi, 0x1000
  855. ;           mov eax, [esi+ebx*4]
  856. ;           test eax, eax
  857. ;           jz @f
  858. ;          and eax, 0xFFFFF000
  859. ;           stdcall map_page, edi, eax
  860.  
  861. @@:
  862.         mov     edi, [lin_addr]
  863.         and     edi, 0xFFFFF000
  864.         mov     ecx, [buf_size]
  865.         add     ecx, 4095
  866.         shr     ecx, 12
  867.         inc     ecx
  868.  
  869.         mov     edx, [ofs]
  870.         shr     edx, 12
  871.         and     edx, 0x3FF
  872.         mov     esi, [ipc_ptab]
  873.  
  874. .map:
  875.         stdcall safe_map_page, [slot], [req_access], [ofs]
  876.         jnc     .exit
  877.         add     dword [ebp-4], 4096
  878.         add     [ofs], 4096
  879.         dec     ecx
  880.         jz      .exit
  881.         add     edi, 0x1000
  882.         inc     edx
  883.         cmp     edx, 0x400
  884.         jnz     .map
  885.         inc     ebx
  886.         mov     eax, [ipc_pdir]
  887.         mov     eax, [eax+ebx*4]
  888.         and     eax, 0xFFFFF000
  889.         jz      .exit
  890.         stdcall map_page, esi, eax, PG_UW
  891.         xor     edx, edx
  892.         jmp     .map
  893.  
  894. .exit:
  895.         pop     eax
  896.         ret
  897. endp
  898.  
  899. proc map_memEx stdcall, lin_addr:dword,slot:dword,\
  900.                         ofs:dword,buf_size:dword,req_access:dword
  901.         push    0 ; initialize number of mapped bytes
  902.  
  903.         cmp     [buf_size], 0
  904.         jz      .exit
  905.  
  906.         mov     eax, [slot]
  907.         shl     eax, 8
  908.         mov     eax, [SLOT_BASE+eax+APPDATA.dir_table]
  909.         and     eax, 0xFFFFF000
  910.  
  911.         stdcall map_page, [proc_mem_pdir], eax, PG_UW
  912.         mov     ebx, [ofs]
  913.         shr     ebx, 22
  914.         mov     esi, [proc_mem_pdir]
  915.         mov     edi, [proc_mem_tab]
  916.         mov     eax, [esi+ebx*4]
  917.         and     eax, 0xFFFFF000
  918.         test    eax, eax
  919.         jz      .exit
  920.         stdcall map_page, edi, eax, PG_UW
  921.  
  922. @@:
  923.         mov     edi, [lin_addr]
  924.         and     edi, 0xFFFFF000
  925.         mov     ecx, [buf_size]
  926.         add     ecx, 4095
  927.         shr     ecx, 12
  928.         inc     ecx
  929.  
  930.         mov     edx, [ofs]
  931.         shr     edx, 12
  932.         and     edx, 0x3FF
  933.         mov     esi, [proc_mem_tab]
  934.  
  935. .map:
  936.         stdcall safe_map_page, [slot], [req_access], [ofs]
  937.         jnc     .exit
  938.         add     dword [ebp-4], 0x1000
  939.         add     edi, 0x1000
  940.         add     [ofs], 0x1000
  941.         inc     edx
  942.         dec     ecx
  943.         jnz     .map
  944. .exit:
  945.         pop     eax
  946.         ret
  947. endp
  948.  
  949. ; in: esi+edx*4 = pointer to page table entry
  950. ; in: [slot], [req_access], [ofs] on the stack
  951. ; in: edi = linear address to map
  952. ; out: CF cleared <=> failed
  953. ; destroys: only eax
  954. proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword
  955.         mov     eax, [esi+edx*4]
  956.         test    al, PG_MAP
  957.         jz      .not_present
  958.         test    al, PG_WRITE
  959.         jz      .resolve_readonly
  960. ; normal case: writable page, just map with requested access
  961. .map:
  962.         stdcall map_page, edi, eax, [req_access]
  963.         stc
  964. .fail:
  965.         ret
  966. .not_present:
  967. ; check for alloc-on-demand page
  968.         test    al, 2
  969.         jz      .fail
  970. ; allocate new page, save it to source page table
  971.         push    ecx
  972.         call    alloc_page
  973.         pop     ecx
  974.         test    eax, eax
  975.         jz      .fail
  976.         or      al, PG_UW
  977.         mov     [esi+edx*4], eax
  978.         jmp     .map
  979. .resolve_readonly:
  980. ; readonly page, probably copy-on-write
  981. ; check: readonly request of readonly page is ok
  982.         test    [req_access], PG_WRITE
  983.         jz      .map
  984. ; find control structure for this page
  985.         pushf
  986.         cli
  987.         cld
  988.         push    ebx ecx
  989.         mov     eax, [slot]
  990.         shl     eax, 8
  991.         mov     eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr]
  992.         test    eax, eax
  993.         jz      .no_hdll
  994.         mov     ecx, [eax+HDLL.fd]
  995. .scan_hdll:
  996.         cmp     ecx, eax
  997.         jz      .no_hdll
  998.         mov     ebx, [ofs]
  999.         and     ebx, not 0xFFF
  1000.         sub     ebx, [ecx+HDLL.base]
  1001.         cmp     ebx, [ecx+HDLL.size]
  1002.         jb      .hdll_found
  1003.         mov     ecx, [ecx+HDLL.fd]
  1004.         jmp     .scan_hdll
  1005. .no_hdll:
  1006.         pop     ecx ebx
  1007.         popf
  1008.         clc
  1009.         ret
  1010. .hdll_found:
  1011. ; allocate page, save it in page table, map it, copy contents from base
  1012.         mov     eax, [ecx+HDLL.parent]
  1013.         add     ebx, [eax+DLLDESCR.data]
  1014.         call    alloc_page
  1015.         test    eax, eax
  1016.         jz      .no_hdll
  1017.         or      al, PG_UW
  1018.         mov     [esi+edx*4], eax
  1019.         stdcall map_page, edi, eax, [req_access]
  1020.         push    esi edi
  1021.         mov     esi, ebx
  1022.         mov     ecx, 4096/4
  1023.         rep movsd
  1024.         pop     edi esi
  1025.         pop     ecx ebx
  1026.         popf
  1027.         stc
  1028.         ret
  1029. endp
  1030.  
  1031. sys_IPC:
  1032. ;input:
  1033. ;  ebx=1 - set ipc buffer area
  1034. ;    ecx=address of buffer
  1035. ;    edx=size of buffer
  1036. ;  eax=2 - send message
  1037. ;    ebx=PID
  1038. ;    ecx=address of message
  1039. ;    edx=size of message
  1040.  
  1041.         dec     ebx
  1042.         jnz     @f
  1043.  
  1044.         mov     eax, [current_slot]
  1045.         pushf
  1046.         cli
  1047.         mov     [eax+APPDATA.ipc_start], ecx    ;set fields in extended information area
  1048.         mov     [eax+APPDATA.ipc_size], edx
  1049.  
  1050.         add     edx, ecx
  1051.         add     edx, 4095
  1052.         and     edx, not 4095
  1053.  
  1054. .touch:
  1055.         mov     eax, [ecx]
  1056.         add     ecx, 0x1000
  1057.         cmp     ecx, edx
  1058.         jb      .touch
  1059.  
  1060.         popf
  1061.         mov     [esp+32], ebx   ;ebx=0
  1062.         ret
  1063.  
  1064. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1065. ;2
  1066. @@:
  1067.         dec     ebx
  1068.         jnz     @f
  1069.  
  1070.         stdcall sys_ipc_send, ecx, edx, esi
  1071.         mov     [esp+32], eax
  1072.         ret
  1073. @@:
  1074.         or      eax, -1
  1075.         mov     [esp+32], eax
  1076.         ret
  1077.  
  1078. ;align 4
  1079. ;proc set_ipc_buff
  1080.  
  1081. ;           mov  eax,[current_slot]
  1082. ;           pushf
  1083. ;           cli
  1084. ;           mov  [eax+APPDATA.ipc_start],ebx     ;set fields in extended information area
  1085. ;           mov  [eax+APPDATA.ipc_size],ecx
  1086. ;
  1087. ;           add ecx, ebx
  1088. ;           add ecx, 4095
  1089. ;           and ecx, not 4095
  1090. ;
  1091. ;.touch:    mov eax, [ebx]
  1092. ;           add ebx, 0x1000
  1093. ;           cmp ebx, ecx
  1094. ;           jb  .touch
  1095. ;
  1096. ;           popf
  1097. ;           xor eax, eax
  1098. ;           ret
  1099. ;endp
  1100.  
  1101. proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
  1102.            locals
  1103.              dst_slot   dd ?
  1104.              dst_offset dd ?
  1105.              buf_size   dd ?
  1106.              used_buf   dd ?
  1107.            endl
  1108.  
  1109.         pushf
  1110.         cli
  1111.  
  1112.         mov     eax, [PID]
  1113.         call    pid_to_slot
  1114.         test    eax, eax
  1115.         jz      .no_pid
  1116.  
  1117.         mov     [dst_slot], eax
  1118.         shl     eax, 8
  1119.         mov     edi, [eax+SLOT_BASE+0xa0] ;is ipc area defined?
  1120.         test    edi, edi
  1121.         jz      .no_ipc_area
  1122.  
  1123.         mov     ebx, edi
  1124.         and     ebx, 0xFFF
  1125.         mov     [dst_offset], ebx
  1126.  
  1127.         mov     esi, [eax+SLOT_BASE+0xa4]
  1128.         mov     [buf_size], esi
  1129.  
  1130.         mov     ecx, [ipc_tmp]
  1131.         cmp     esi, 0x40000-0x1000; size of [ipc_tmp] minus one page
  1132.         jbe     @f
  1133.         push    esi edi
  1134.         add     esi, 0x1000
  1135.         stdcall alloc_kernel_space, esi
  1136.         mov     ecx, eax
  1137.         pop     edi esi
  1138. @@:
  1139.         mov     [used_buf], ecx
  1140.         stdcall map_mem, ecx, [dst_slot], \
  1141.                 edi, esi, PG_SW
  1142.  
  1143.         mov     edi, [dst_offset]
  1144.         add     edi, [used_buf]
  1145.         cmp     dword [edi], 0
  1146.         jnz     .ipc_blocked          ;if dword [buffer]<>0 - ipc blocked now
  1147.  
  1148.         mov     edx, dword [edi+4]
  1149.         lea     ebx, [edx+8]
  1150.         add     ebx, [msg_size]
  1151.         cmp     ebx, [buf_size]
  1152.         ja      .buffer_overflow       ;esi<0 - not enough memory in buffer
  1153.  
  1154.         mov     dword [edi+4], ebx
  1155.         mov     eax, [TASK_BASE]
  1156.         mov     eax, [eax+0x04]        ;eax - our PID
  1157.         add     edi, edx
  1158.         mov     [edi], eax
  1159.         mov     ecx, [msg_size]
  1160.  
  1161.         mov     [edi+4], ecx
  1162.         add     edi, 8
  1163.         mov     esi, [msg_addr]
  1164.        ;    add esi, new_app_base
  1165.         cld
  1166.         rep movsb
  1167.  
  1168.         mov     ebx, [ipc_tmp]
  1169.         mov     edx, ebx
  1170.         shr     ebx, 12
  1171.         xor     eax, eax
  1172.         mov     [page_tabs+ebx*4], eax
  1173.         invlpg  [edx]
  1174.  
  1175.         mov     ebx, [ipc_pdir]
  1176.         mov     edx, ebx
  1177.         shr     ebx, 12
  1178.         xor     eax, eax
  1179.         mov     [page_tabs+ebx*4], eax
  1180.         invlpg  [edx]
  1181.  
  1182.         mov     ebx, [ipc_ptab]
  1183.         mov     edx, ebx
  1184.         shr     ebx, 12
  1185.         xor     eax, eax
  1186.         mov     [page_tabs+ebx*4], eax
  1187.         invlpg  [edx]
  1188.  
  1189.         mov     eax, [dst_slot]
  1190.         shl     eax, 8
  1191.         or      [eax+SLOT_BASE+0xA8], dword 0x40
  1192.         push    0
  1193.         jmp     .ret
  1194. .no_pid:
  1195.         popf
  1196.         mov     eax, 4
  1197.         ret
  1198. .no_ipc_area:
  1199.         popf
  1200.         xor     eax, eax
  1201.         inc     eax
  1202.         ret
  1203. .ipc_blocked:
  1204.         push    2
  1205.         jmp     .ret
  1206. .buffer_overflow:
  1207.         push    3
  1208. .ret:
  1209.         mov     eax, [used_buf]
  1210.         cmp     eax, [ipc_tmp]
  1211.         jz      @f
  1212.         stdcall free_kernel_space, eax
  1213. @@:
  1214.         pop     eax
  1215.         popf
  1216.         ret
  1217. endp
  1218.  
  1219. align 4
  1220. sysfn_meminfo:
  1221.  
  1222.         ;   add ecx, new_app_base
  1223.         cmp     ecx, OS_BASE
  1224.         jae     .fail
  1225.  
  1226.         mov     eax, [pg_data.pages_count]
  1227.         mov     [ecx], eax
  1228.         shl     eax, 12
  1229.         mov     [esp+32], eax
  1230.         mov     eax, [pg_data.pages_free]
  1231.         mov     [ecx+4], eax
  1232.         mov     eax, [pg_data.pages_faults]
  1233.         mov     [ecx+8], eax
  1234.         mov     eax, [heap_size]
  1235.         mov     [ecx+12], eax
  1236.         mov     eax, [heap_free]
  1237.         mov     [ecx+16], eax
  1238.         mov     eax, [heap_blocks]
  1239.         mov     [ecx+20], eax
  1240.         mov     eax, [free_blocks]
  1241.         mov     [ecx+24], eax
  1242.         ret
  1243. .fail:
  1244.         or      dword [esp+32], -1
  1245.         ret
  1246.  
  1247. align 4
  1248. f68:
  1249.         cmp     ebx, 4
  1250.         jbe     sys_sheduler
  1251.  
  1252.         cmp     ebx, 11
  1253.         jb      .fail
  1254.  
  1255.         cmp     ebx, 27
  1256.         ja      .fail
  1257.  
  1258.         jmp     dword [f68call+ebx*4-11*4]
  1259. .11:
  1260.         call    init_heap
  1261.         mov     [esp+32], eax
  1262.         ret
  1263. .12:
  1264.         stdcall user_alloc, ecx
  1265.         mov     [esp+32], eax
  1266.         ret
  1267. .13:
  1268.         stdcall user_free, ecx
  1269.         mov     [esp+32], eax
  1270.         ret
  1271. .14:
  1272.         cmp     ecx, OS_BASE
  1273.         jae     .fail
  1274.         mov     edi, ecx
  1275.         call    get_event_ex
  1276.         mov     [esp+32], eax
  1277.         ret
  1278. .16:
  1279.         test    ecx, ecx
  1280.         jz      .fail
  1281.         cmp     ecx, OS_BASE
  1282.         jae     .fail
  1283.         stdcall get_service, ecx
  1284.         mov     [esp+32], eax
  1285.         ret
  1286. .17:
  1287.         call    srv_handlerEx   ;ecx
  1288.         mov     [esp+32], eax
  1289.         ret
  1290. .19:
  1291.         cmp     ecx, OS_BASE
  1292.         jae     .fail
  1293.         stdcall load_library, ecx
  1294.         mov     [esp+32], eax
  1295.         ret
  1296. .20:
  1297.         mov     eax, edx
  1298.         mov     ebx, ecx
  1299.         call    user_realloc            ;in: eax = pointer, ebx = new size
  1300.         mov     [esp+32], eax
  1301.         ret
  1302. .21:
  1303.         cmp     ecx, OS_BASE
  1304.         jae     .fail
  1305.  
  1306.         cmp     edx, OS_BASE
  1307.         jae     .fail
  1308.  
  1309.         stdcall load_pe_driver, ecx, edx
  1310.         mov     [esp+32], eax
  1311.         ret
  1312. .22:
  1313.         cmp     ecx, OS_BASE
  1314.         jae     .fail
  1315.  
  1316.         stdcall shmem_open, ecx, edx, esi
  1317.         mov     [esp+24], edx
  1318.         mov     [esp+32], eax
  1319.         ret
  1320.  
  1321. .23:
  1322.         cmp     ecx, OS_BASE
  1323.         jae     .fail
  1324.  
  1325.         stdcall shmem_close, ecx
  1326.         mov     [esp+32], eax
  1327.         ret
  1328. .24:
  1329.         mov     eax, [current_slot]
  1330.         xchg    ecx, [eax+APPDATA.exc_handler]
  1331.         xchg    edx, [eax+APPDATA.except_mask]
  1332.         mov     [esp+32], ecx ; reg_eax+8
  1333.         mov     [esp+20], edx ; reg_ebx+8
  1334.         ret
  1335. .25:
  1336.         cmp     ecx, 32
  1337.         jae     .fail
  1338.         mov     eax, [current_slot]
  1339.         btr     [eax+APPDATA.except_mask], ecx
  1340.         setc    byte[esp+32]
  1341.         jecxz   @f
  1342.         bts     [eax+APPDATA.except_mask], ecx
  1343. @@:
  1344.         ret
  1345.  
  1346. .26:
  1347.         stdcall user_unmap, ecx, edx, esi
  1348.         mov     [esp+32], eax
  1349.         ret
  1350.  
  1351. .27:
  1352.         cmp     ecx, OS_BASE
  1353.         jae     .fail
  1354.  
  1355.         stdcall load_file_umode, ecx
  1356.         mov     [esp+24], edx
  1357.         mov     [esp+32], eax
  1358.         ret
  1359.  
  1360. .fail:
  1361.         xor     eax, eax
  1362.         mov     [esp+32], eax
  1363.         ret
  1364.  
  1365.  
  1366. align 4
  1367. f68call:   ; keep this table closer to main code
  1368.  
  1369.            dd f68.11   ; init_heap
  1370.            dd f68.12   ; user_alloc
  1371.            dd f68.13   ; user_free
  1372.            dd f68.14   ; get_event_ex
  1373.            dd f68.fail ; moved to f68.24
  1374.            dd f68.16   ; get_service
  1375.            dd f68.17   ; call_service
  1376.            dd f68.fail ; moved to f68.25
  1377.            dd f68.19   ; load_dll
  1378.            dd f68.20   ; user_realloc
  1379.            dd f68.21   ; load_driver
  1380.            dd f68.22   ; shmem_open
  1381.            dd f68.23   ; shmem_close
  1382.            dd f68.24   ; set exception handler
  1383.            dd f68.25   ; unmask exception
  1384.            dd f68.26   ; user_unmap
  1385.            dd f68.27   ; load_file_umode
  1386.  
  1387.  
  1388. align 4
  1389. proc load_pe_driver stdcall, file:dword, cmdline:dword
  1390.         push    esi
  1391.  
  1392.         stdcall load_PE, [file]
  1393.         test    eax, eax
  1394.         jz      .fail
  1395.  
  1396.         mov     esi, eax
  1397.         push    [cmdline]
  1398.         push    DRV_ENTRY
  1399.         call    eax
  1400.         pop     ecx
  1401.         pop     ecx
  1402.         test    eax, eax
  1403.         jz      .fail
  1404.  
  1405.         mov     [eax+SRV.entry], esi
  1406.         pop     esi
  1407.         ret
  1408.  
  1409. .fail:
  1410.         xor     eax, eax
  1411.         pop     esi
  1412.         ret
  1413. endp
  1414.  
  1415. align 4
  1416. proc create_ring_buffer stdcall, size:dword, flags:dword
  1417.            locals
  1418.              buf_ptr  dd ?
  1419.            endl
  1420.  
  1421.         mov     eax, [size]
  1422.         test    eax, eax
  1423.         jz      .fail
  1424.  
  1425.         add     eax, eax
  1426.         stdcall alloc_kernel_space, eax
  1427.         test    eax, eax
  1428.         jz      .fail
  1429.  
  1430.         push    ebx
  1431.  
  1432.         mov     [buf_ptr], eax
  1433.  
  1434.         mov     ebx, [size]
  1435.         shr     ebx, 12
  1436.         push    ebx
  1437.  
  1438.         stdcall alloc_pages, ebx
  1439.         pop     ecx
  1440.  
  1441.         test    eax, eax
  1442.         jz      .mm_fail
  1443.  
  1444.         push    edi
  1445.  
  1446.         or      eax, [flags]
  1447.         mov     edi, [buf_ptr]
  1448.         mov     ebx, [buf_ptr]
  1449.         mov     edx, ecx
  1450.         shl     edx, 2
  1451.         shr     edi, 10
  1452. @@:
  1453.         mov     [page_tabs+edi], eax
  1454.         mov     [page_tabs+edi+edx], eax
  1455.         invlpg  [ebx]
  1456.         invlpg  [ebx+0x10000]
  1457.         add     eax, 0x1000
  1458.         add     ebx, 0x1000
  1459.         add     edi, 4
  1460.         dec     ecx
  1461.         jnz     @B
  1462.  
  1463.         mov     eax, [buf_ptr]
  1464.         pop     edi
  1465.         pop     ebx
  1466.         ret
  1467. .mm_fail:
  1468.         stdcall free_kernel_space, [buf_ptr]
  1469.         xor     eax, eax
  1470.         pop     ebx
  1471. .fail:
  1472.         ret
  1473. endp
  1474.  
  1475.  
  1476. align 4
  1477. proc print_mem
  1478.         mov     edi, BOOT_VAR + 0x9104
  1479.         mov     ecx, [edi-4]
  1480.         test    ecx, ecx
  1481.         jz      .done
  1482.  
  1483. @@:
  1484.         mov     eax, [edi]
  1485.         mov     edx, [edi+4]
  1486.         add     eax, [edi+8]
  1487.         adc     edx, [edi+12]
  1488.  
  1489.         DEBUGF  1, "K : E820 %x%x - %x%x type %d\n", \
  1490.                     [edi+4], [edi],\
  1491.                     edx, eax, [edi+16]
  1492.         add     edi, 20
  1493.         dec     ecx
  1494.         jnz     @b
  1495. .done:
  1496.         ret
  1497. endp
  1498.