home *** CD-ROM | disk | FTP | other *** search
/ Boot Disc 15 / boot-disc-1997-11.iso / Debian / Tools / LODLIN16.ZIP / LODLIN16 / SRC / LOADLINM.ASM < prev    next >
Assembly Source File  |  1996-03-30  |  24KB  |  785 lines

  1. ;   >>> this is file LOADLINM.ASM
  2. ;============================================================================
  3. ;   LOADLIN v1.6 (C) 1994..1996 Hans Lermen (lermen@elserv.ffm.fgan.de)
  4. ;
  5. ;   This program is free software; you can redistribute it and/or modify
  6. ;   it under the terms of the GNU General Public License as published by
  7. ;   the Free Software Foundation; either version 2 of the License, or
  8. ;   (at your option) any later version.
  9. ;
  10. ;   This program is distributed in the hope that it will be useful,
  11. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. ;   GNU General Public License for more details.
  14. ;
  15. ;   You should have received a copy of the GNU General Public License
  16. ;   along with this program; if not, write to the Free Software
  17. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ;
  19. ;----------------------------------------------------------------------------
  20. ;   Comments and bug reports are welcome and may be sent to:
  21. ;   E-Mail:    lermen@elserv.ffm.fgan.de
  22. ;   SnailMail: Hans Lermen
  23. ;              Am Muehlenweg 38
  24. ;              D53424 REMAGEN-Unkelbach
  25. ;              GERMANY
  26. ;
  27. ;============================================================================
  28.  
  29. ;---------------------------------------------------------------------------
  30.  
  31.  
  32.  
  33. call_pmode_routine proc near
  34. ; NOTE: must have called get_VCPI_interface before this
  35. ;       _AND_ must be already moved high, else the pagetable
  36. ;       will not be aligned.
  37. ; input:
  38. ;  AX  = offset of protected mode routine
  39. ; The called routine will have a pointer in ebp to a pushad_struct
  40. ; of the other input registers, and all segment register point to
  41. ; High_seg
  42. ;
  43. @@regs struc
  44.   pushAD_struc @@
  45. @@regs ends
  46.           pushf
  47.           CLI
  48.           pushad
  49.           mov    ebp,esp
  50.                  ; ┌─────  IRET stack for return to VM86
  51.           push   0
  52.            push   gs
  53.           push   0
  54.            push   fs
  55.           push   0
  56.            push   ds
  57.           push   0
  58.            push   es
  59.           push   0
  60.            push   ss
  61.           push   ebp
  62.           sub    sp,4           ; space for EFLAGS
  63.           push   0
  64.            push   cs
  65.           push   0
  66.            push   offset @@pmode_return
  67.                  ; └──────  IRET stack for return to VM86
  68.           mov    cs:pmode_return_esp,esp
  69.           lea    ax,@@pmode_task
  70.           movzx  eax,ax
  71.           mov    dword ptr protected_mode_target,eax
  72.           mov    word ptr protected_mode_target+4,g_code
  73.           movzx   esi,cs:High_Seg
  74.           shl     esi,4
  75.           lea     si,our_CR3[si]
  76.           mov     ax,0DE0Ch
  77.           int     emm_int    ; jumps to protected mode
  78.           ; and comes here in 16-bit protected mode
  79. @@pmode_task:
  80.           mov     ax,g_data
  81.           mov     ss,ax
  82.           mov     ds,ax
  83.           mov     es,ax
  84.           mov     fs,ax
  85.           mov     gs,ax
  86.           mov     esp,cs:pmode_return_esp
  87.  
  88.                              ; ebp pointing to pushad_struct
  89.           mov     ax, word ptr [bp].@@eax
  90.           call    ax         ; call the routine
  91.  
  92.           ; now we return to VM86 mode
  93.           cli      ; to be save
  94.           mov     ax,g_core    ; selector for addressing first MByte
  95.           mov     ds,ax
  96.           .386p
  97.           CLTS                 ; clear taskswitch flag
  98.           .386
  99.           mov     eax,0DE0Ch
  100.           call    fword ptr cs:server_vcpi_entry  ; back to VM86
  101.  
  102.           ; and returns here in VM86 mode
  103. @@pmode_return:
  104.           popad
  105.           popf
  106.           ret
  107. call_pmode_routine endp
  108.  
  109.  
  110. IF 0
  111. AUXPAGE       =  (modul_end-code_org0) ; behind our code
  112. ELSE
  113. AUXPAGE       =  0 ; at start of our segment, only used in protected mode
  114. ENDIF
  115. AUXPAGE_size  =  02000h
  116. AUXPAGE_entry =  (AUXPAGE shr (12-2))
  117. AUXPAGE_S     =  AUXPAGE
  118. AUXPAGE_T     =  AUXPAGE+AUXPAGE_size
  119.  
  120. AUXPAGE_S_entry equ page0+AUXPAGE_entry[bx]
  121. AUXPAGE_T_entry equ page0+(AUXPAGE_entry+(AUXPAGE_size shr (12-2)))[bx]
  122. AUXPAGE_BITS  =  3       ; writeable, present
  123.  
  124. move_anywhere_vcpi proc near
  125. ; input:
  126. ;   ESI= linear source address
  127. ;   EDI= linear target address
  128. ;    CX= size to move, must be <= 4096 !!!
  129. ; output:
  130. ;    all registers preserved
  131.                 ; we are in VM86 and at this point assume to have VCPI
  132.         push    ax
  133.         lea     ax,@@pmove
  134.         call    call_pmode_routine
  135.         pop     ax
  136.         ret
  137.                 ; this will be executed in 16-bit protected mode
  138. @@pmove:
  139. @@regs struc
  140.   pushAD_struc @@
  141. @@regs ends
  142.                 ; save pagetable-entries
  143.         mov     bx,High_Seg
  144.         shr     bx,(12-4-2)
  145.         push    AUXPAGE_S_entry
  146.         push    AUXPAGE_S_entry+4
  147.         push    AUXPAGE_T_entry
  148.         push    AUXPAGE_T_entry+4
  149.  
  150. mmm     macro   reg,st
  151.         mov     eax,[bp].@@e®
  152.         mov     reg,ax
  153.         and     reg,0fffh
  154.         lea     reg,[reg]+AUXPAGE_&st
  155.         and     ax,0f000h
  156.         or      al,AUXPAGE_BITS
  157.         mov     AUXPAGE_&st&_entry,eax
  158.         add     eax,1000h
  159.         mov     AUXPAGE_&st&_entry+4,eax
  160.         endm
  161.  
  162.         mmm     si,S        ; map source
  163.         mmm     di,T        ; map target
  164.           .386p
  165.         mov     eax,CR3     ; flush TLB
  166.         mov     CR3,eax
  167.           .386
  168.  
  169.         cld
  170.         movzx   ecx,cx
  171.         ror     ecx,2
  172.         rep movsd
  173.         rol     ecx,2
  174.         rep movsb
  175.                 ; restore pagetable-entries
  176.         pop     AUXPAGE_T_entry+4
  177.         pop     AUXPAGE_T_entry
  178.         pop     AUXPAGE_S_entry+4
  179.         pop     AUXPAGE_S_entry
  180.         ret
  181. move_anywhere_vcpi endp
  182.  
  183.  
  184. ;---------------------------------------------------------------
  185.  
  186.  
  187. move_anywhere_INT15 proc near
  188. ; input: ESI = source linear address
  189. ;        EDI = destination linear address
  190. ;        CX  = count
  191. ; returns:
  192. ;        all registers preserved
  193. ;
  194. @@descript    struc
  195.   @@limit     dw    ?
  196.   @@base0     dw    ?
  197.   @@base16    db    ?
  198.   @@typbyte   db    ?
  199.   @@limit16   db    ?
  200.   @@base24    db    ?
  201. @@descript    ends
  202.         push_   es,eax,esi,edi,ecx
  203.         mov     cs:@@src.@@base0,si
  204.         shld    eax,esi,16
  205.         mov     cs:@@src.@@base16,al
  206.         mov     cs:@@src.@@base24,ah
  207.         mov     cs:@@dest.@@base0,di
  208.         shld    eax,edi,16
  209.         mov     cs:@@dest.@@base16,al
  210.         mov     cs:@@dest.@@base24,ah
  211.         mov     cx,(1000h/2)  ; force to be one page
  212.                               ; NOTE: INT15 moves are in WORDS,
  213.                               ; because we always move 1000h,
  214.                               ; we simple do it also for the last page
  215.         push    cs
  216.         pop     es
  217.         lea     si,@@gdt
  218.         mov     ax,08700h
  219.         int     15h
  220.         pop_    es,eax,esi,edi,ecx
  221.         ret
  222.         align   qword
  223. @@gdt   @@descript <0,0,0,0,0,0>
  224.         @@descript <0,0,0,0,0,0>
  225. @@src   @@descript <0ffffh,0,0,093h,0,0>
  226. @@dest  @@descript <0ffffh,0,0,093h,0,0>
  227.         @@descript <0,0,0,0,0,0>      ; BIOS CS
  228.         @@descript <0,0,0,0,0,0>      ; BIOS SS
  229. move_anywhere_INT15 endp
  230.  
  231. ;============================================================================
  232.  
  233. DUMMY_XMS_BLOCK_START = 100000h
  234.  
  235. XMS_GET_VERSION   =  0
  236. XMS_QUERY_FREE    =  8
  237. XMS_ALLOC         =  9
  238. XMS_FREE          =  0ah
  239. XMS_MOVE_BLOCK    =  0bh
  240. XMS_LOCK_BLOCK    =  0ch
  241. XMS_UNLOCK_BLOCK  =  0dh
  242.  
  243. xmscall   macro   function
  244.           mov     ah,function
  245.           call    cs:xms_entry
  246.           endm
  247.  
  248. check_for_XMS  proc near
  249.           push_   ds,es,ax,bx
  250.  
  251.           mov     cs:xms_entry,0
  252.           mov     cs:xms_avail,0
  253.           mov     ax,4300h
  254.           INT     2fh
  255.           cmp     al,80h
  256.           jnz     @@ex
  257.           mov     ax,4310h
  258.           INT     2fh
  259.           mov     word ptr cs:xms_entry,bx
  260.           mov     word ptr cs:xms_entry+2,es
  261.           xmscall XMS_GET_VERSION
  262.           cmp     ax,200h
  263.           jb      @@ex0
  264.           xmscall XMS_QUERY_FREE
  265.           or      ax,ax
  266.           jz      @@ex0
  267.           mov     cs:xms_avail,ax
  268. @@ex:
  269.           pop_    ds,es,ax,bx
  270.           cmp     cs:xms_entry,0
  271.           ret
  272. @@ex0:
  273.           mov     cs:xms_entry,0
  274.           jmp     @@ex
  275. check_for_XMS  endp
  276.  
  277. allocate_xms_block proc near
  278.           push_   bx,dx
  279.           cmp     cs:xms_entry,0
  280.           je      @@ex0
  281.           mov     dx,cs:xms_avail
  282.           xmscall XMS_ALLOC
  283.           or      ax,ax
  284.           je      @@ex0
  285.           mov     cs:xms_handle,dx
  286. @@ex:
  287.           pop_    bx,dx
  288.           or      eax,eax
  289.           ret
  290. @@ex0:
  291.           xor     eax,eax
  292.           jmp     @@ex
  293. allocate_xms_block endp
  294.  
  295.  
  296. lock_xms_block proc near
  297.                                       ; try to lock the XMS block
  298.                                       ; (needed to get the phys.address)
  299.           push_   ax,bx,dx
  300.           mov     dx,cs:xms_handle
  301.           xmscall XMS_LOCK_BLOCK
  302.           or      ax,ax
  303.           je      @@err
  304.           mov     word ptr cs:xms_phys_addr,bx
  305.           mov     word ptr cs:xms_phys_addr+2,dx
  306.           pop_    ax,bx,dx
  307.           ret
  308. @@err:
  309.           push    cs
  310.           pop     ds
  311.           lea     dx,@@tx
  312.           call    print
  313.           jmp     exit_to_dos
  314. @@tx      db      13,10,'Cannot lock XMS memory',13,10,'$'
  315. lock_xms_block endp
  316.  
  317.  
  318. free_xms_block proc near
  319.           push_   ax,bx,dx
  320.           mov     dx,cs:xms_handle
  321.           xmscall XMS_UNLOCK_BLOCK
  322.           mov     dx, cs:xms_handle
  323.           xmscall XMS_FREE
  324.           pop_    ax,bx,dx
  325.           ret
  326. free_xms_block endp
  327.  
  328.  
  329. move_anywhere_xms proc near
  330. ; input:
  331. ;   ESI= linear source address   (must be in lowmem )
  332. ;   EDI= linear target address
  333. ;    CX= size to move, must be <= 4096 !!!  (actually _is_ always 4096)
  334. ; output:
  335. ;    all registers preserved
  336.           cmp     edi,DUMMY_XMS_BLOCK_START
  337.           jb      move_simple
  338.           pushad
  339.           push    ds
  340.           mov     ecx,1000h   ; force a length of one page to move
  341.                               ; NOTE: XMS moves have to be even,
  342.                               ; because we alway move 1000h,
  343.                               ; we simple do it also for the last page
  344.           mov     @@length,ecx
  345.           sub     edi,DUMMY_XMS_BLOCK_START
  346.           mov     @@doffs,edi
  347.           mov     di,xms_handle
  348.           mov     @@dhandle,di
  349.           ror     esi,4
  350.           mov     word ptr @@soffs+2,si
  351.           xor     si,si
  352.           rol     esi,4
  353.           mov     word ptr @@soffs,si
  354.           lea     si,@@length
  355.           push    cs
  356.           pop     ds
  357.           xmscall XMS_MOVE_BLOCK
  358.           pop     ds
  359.           popad
  360.           ret
  361. @@length     dd      ?
  362. @@shandle    dw      0
  363. @@soffs      dd      ?
  364. @@dhandle    dw      ?
  365. @@doffs      dd      ?
  366. move_anywhere_xms endp
  367.  
  368.  
  369. ;--------------------------------------------------------------------
  370.  
  371. move_simple  proc near
  372. ; input:
  373. ;   ESI= linear source address
  374. ;   EDI= linear target address
  375. ;    CX= size to move, must be <= 4096 !!!
  376. ; output:
  377. ;    all registers preserved
  378.         pushad
  379.         push_   ds,es
  380.         movzx   ecx,cx
  381.         cld
  382.         ror     edi,4
  383.         mov     es,di
  384.         xor     di,di
  385.         rol     edi,4
  386.         ror     esi,4
  387.         mov     ds,si
  388.         xor     si,si
  389.         rol     esi,4
  390.         ror     ecx,2
  391.         rep movsd
  392.         rol     ecx,2
  393.         rep movsb
  394. @@ex:
  395.         pop_    ds,es
  396.         popad
  397.         ret
  398. move_simple  endp
  399.  
  400.  
  401.  
  402.  
  403. build_buffer_heap proc near
  404.         pushad
  405.                 ; first we setup the normal low heap
  406.                 ; (why not use it)
  407.         movzx    eax,kernel_load_frame
  408.         shl      eax,4
  409.         mov      heap_ptr,eax
  410.         movzx    eax,High_Seg       ; NOTE: this is page aligned !
  411.         shl      eax,4
  412.         mov      heap_end,eax
  413.         sub      eax,heap_ptr
  414.         shr      eax,12
  415.         mov      heap_max_pages,eax
  416.  
  417.                 ; now we try to get some extended memory
  418.         cmp     need_mapped_put_buffer,0
  419.         jz      @@err
  420.         cmp     cpu_type,cpu_386V86
  421.         je      @@vcpi
  422.                 ; we check what we can use to access extended memory
  423.         call    check_for_XMS
  424.         jz      @@need_int15
  425.         cmp     cs:xms_avail,128
  426.         jb      @@need_int15
  427.         sub     cs:xms_avail,64        ; leave a 64K minimum for system
  428.         call    allocate_xms_block
  429.         jz      @@need_int15
  430.         movzx   eax,cs:xms_avail
  431.         shr     eax,2        ; from 1KB to 4KB
  432.         add     heap_max_pages,eax
  433.         mov     high_heap_ptr,DUMMY_XMS_BLOCK_START
  434.         mov     high_mem_access,USING_XMS
  435.         mov     move_anywhere, offset move_anywhere_xms
  436. @@ex:
  437.         mov      eax,heap_max_pages
  438.         shl      eax,12
  439.         mov      load_buffer_size,eax
  440.         popad
  441.         ret
  442.  
  443. @@need_int15:
  444.         mov     ax,08800h
  445.         int     15h
  446.         sub     ax,64+64     ; leave HMA untouched, we need 64Kminimum
  447.                              ; (else we would waste more mem than winning)
  448.         jbe     @@err
  449.         movzx   eax,ax
  450.         shr     eax,2        ; from 1KB to 4KB
  451.         add     heap_max_pages,eax
  452.         mov     high_heap_ptr,0110000h
  453.         mov     high_mem_access,USING_INT15
  454.         mov     move_anywhere, offset move_anywhere_int15
  455.         jmp     @@ex
  456. @@err:
  457.         mov     high_mem_access,0
  458.         mov     move_anywhere, offset move_simple
  459.         jmp     @@ex
  460. @@vcpi:
  461.         cmp     have_VCPI,0
  462.         jz      @@ex
  463.         push    edx
  464.         mov     ax,0DE03h   ; get avail 4K VCPI-page
  465.         int     emm_int
  466.         sub     edx,(64/4)      ; leave a 64K minimum for system
  467.         jb      @@err
  468.         add     heap_max_pages,edx
  469.         mov     high_mem_access,USING_VCPI
  470.         mov     move_anywhere, offset move_anywhere_vcpi
  471.         pop     edx
  472.         jmp     @@ex
  473. build_buffer_heap endp
  474.  
  475.  
  476. get_buffer_from_heap proc near
  477. ; output: EAX = linear address of 4K buffer, page aligned
  478. ;               (if XMS, then the offset within the buffer)
  479. ;         CARRY =1, if memory overflow
  480.         cmp     heap_max_pages,0
  481.         jna     @@err
  482.         dec     heap_max_pages
  483.         mov     eax,heap_ptr
  484.         cmp     eax,heap_end
  485.         jnb     @@high
  486.         add     heap_ptr,1000h
  487. @@ex1:
  488.         clc
  489. @@ex:
  490.         ret
  491. @@high:
  492.         cmp     high_mem_access,USING_VCPI   ; what heap are we using
  493.         je      @@vcpi
  494.         mov     eax,high_heap_ptr
  495.         add     high_heap_ptr,1000h
  496.         jmp     @@ex1
  497. @@vcpi:
  498.         push    edx
  499.         mov     ax,0DE04h   ; get 4K VCPI-page
  500.         int     emm_int
  501.         mov     eax,edx
  502.         and     ax,0f000h
  503.         pop     edx
  504.         jmp     @@ex1
  505. @@err:
  506.         xor     eax,eax
  507.         stc
  508.         jmp     @@ex
  509. get_buffer_from_heap endp
  510.  
  511. free_extended_memory proc near
  512.         cmp      need_mapped_put_buffer,0
  513.         jz       @@ex
  514.         cmp      high_mem_access,USING_XMS
  515.         je       @@xms
  516.         cmp      high_mem_access,USING_VCPI
  517.         jne      @@ex
  518. @@vcpi:
  519.         push_    eax,bx,edx
  520.         mov      bx,word ptr pageadjlist.ncount
  521.         shl      bx,2
  522. @@loop:
  523.         sub      bx,4
  524.         jb       @@ex1
  525.         mov      edx,pageadjlist.sources[bx]
  526.         cmp      edx,0100000h
  527.         jb       @@ex1
  528.         mov      ax,0DE05h   ; free 4K VCPI-page
  529.         int      emm_int
  530.         jmp      @@loop
  531. @@ex1:
  532.         pop_     eax,bx,edx
  533. @@ex:
  534.         ret
  535. @@xms:
  536.         call     free_xms_block
  537.         jmp      @@ex
  538. free_extended_memory endp
  539.  
  540.  
  541. final_page_adjust_list_handling proc near
  542.         cmp      need_mapped_put_buffer,0
  543.         jz       @@ex
  544.         cmp      high_mem_access,USING_XMS
  545.         jne      @@ex
  546.  
  547.         push_    eax,bx
  548.         call     lock_xms_block
  549.         mov      bx,word ptr pageadjlist.ncount
  550.         shl      bx,2
  551. @@loop:
  552.         sub      bx,4
  553.         jb       @@ex1
  554.         mov      eax,pageadjlist.sources[bx]
  555.         sub      eax,DUMMY_XMS_BLOCK_START
  556.         jb       @@ex1
  557.         add      eax,xms_phys_addr
  558.         mov      pageadjlist.sources[bx],eax
  559.         jmp      @@loop
  560. @@ex1:
  561.         pop_     eax,bx
  562. @@ex:
  563.         ret
  564. final_page_adjust_list_handling endp
  565.  
  566.  
  567.  
  568. open_new_mapped_block proc near
  569. ; input:
  570. ;   EDI = linear address of final target address
  571.         cmp      need_mapped_put_buffer,0
  572.         jz       @@ex
  573.         push_    bx,edi
  574.         mov      bx,word ptr pageadjlist.number_of_blocks
  575.         shl      bx,3    ; * sizeof(pblock)
  576.         and      di,0f000h
  577.         mov      pageadjlist.blocks.taddr[bx],edi
  578.         mov      di,word ptr pageadjlist.ncount
  579.         mov      pageadjlist.blocks.tstart[bx],di
  580.         mov      pageadjlist.blocks.tcount[bx],0
  581.         inc      pageadjlist.number_of_blocks
  582.         mov      do_mapped_put_buffer,1    ; notice 'put_buffer' what to do
  583.         pop_     bx,edi
  584. @@ex:
  585.         ret
  586. open_new_mapped_block endp
  587.  
  588.  
  589. map_high_page proc near
  590. ; input:
  591. ;   EDI = linear address of source address
  592. ;   because this is called strict sequentially, the target address
  593. ;   is allways given by the next free entry in the pageadjlist
  594.         cmp      need_mapped_put_buffer,0
  595.         jz       @@ex
  596.         push_    bx,edi
  597.         mov      bx,word ptr pageadjlist.ncount
  598.         shl      bx,2
  599.         and      di,0f000h
  600.         mov      pageadjlist.sources[bx],edi
  601.         inc      pageadjlist.ncount
  602.         mov      bx,word ptr pageadjlist.number_of_blocks
  603.         dec      bx
  604.         shl      bx,3    ; * sizeof(pblock)
  605.         inc      pageadjlist.blocks.tcount[bx]
  606.         pop_     bx,edi
  607. @@ex:
  608.         ret
  609. map_high_page endp
  610.  
  611. put_buffer  proc near
  612. ; input:
  613. ;     AX=  count
  614. ;    EDI=  linear destination address (may be > 0100000h)
  615. ;  DS:DX=  source address in lowmem
  616. ; output:
  617. ;   none, all registers preserved
  618. ;   in case of memory overflow it doesn't return (jumps to exit_to_dos)
  619. ;
  620.         pushad
  621.         push_   ds,es
  622.         movzx   ecx,ax
  623.         cmp     cs:need_mapped_put_buffer,0
  624.         jnz     @@mapped
  625.                 ; we can mov it normally
  626.         cld
  627.         ror     edi,4
  628.         mov     es,di
  629.         xor     di,di
  630.         rol     edi,4
  631.         mov     si,dx
  632.         ror     ecx,2
  633.         rep movsd
  634.         rol     ecx,2
  635.         rep movsb
  636. @@ex:
  637.         pop_    ds,es
  638.         popad
  639.         ret
  640. @@mapped:                  ; do high move
  641.         call    get_buffer_from_heap
  642.         jc      @@err
  643.                            ; we don't need EDI any more, because
  644.                            ; if we come here we are writing
  645.                            ; strict sequentialy and have set the
  646.                            ; starting address of the block
  647.                            ; via open_new_mapped_block
  648.         mov     edi,eax
  649.         mov     si,ds
  650.         movzx   esi,si
  651.         shl     esi,4
  652.         movzx   edx,dx
  653.         add     esi,edx
  654.         call    map_high_page
  655.         call    move_anywhere
  656.         jmp     @@ex
  657. @@err:
  658.         pop_    ds,es
  659.         popad
  660.         DosCall  DOS_CLOSE_FILE
  661.         lea     dx,@@tx
  662.         call    print
  663.         jmp     exit_to_dos
  664. @@tx    db      13,10,'Out of memory (may be low or extended)',13,10,'$'
  665. put_buffer  endp
  666.  
  667. ; ---------------------------------------------------------------
  668. ; initrd stuff
  669.  
  670. MAXPHYSMEM_FOR_INT15   = 1000000h
  671.  
  672. load_initrd proc near
  673.         cmp      cs:option_initrd,0
  674.         jz       @@ex
  675.         pushad
  676.         cmp      need_mapped_put_buffer,0
  677.         jz       @@err_unable
  678.         call     get_effective_physmem
  679.         mov      end_of_physmem,eax
  680.         cmp      high_mem_access,USING_INT15
  681.         jne      @@1
  682.                  ; INT15 on some BIOSes will not access above 16Mb
  683.         cmp      eax,MAXPHYSMEM_FOR_INT15
  684.         jbe      @@1
  685.         mov      eax,MAXPHYSMEM_FOR_INT15
  686. @@1:
  687.         mov      @@end_of_physmem,eax
  688.         mov      ax,DOS_OPEN_FILE shl 8
  689.         lea      dx,rdimage_name
  690.         DosInt
  691.         jc       @@err_open
  692.         mov      fhandle,ax
  693.         mov      bx,ax
  694.         call     get_filesize
  695.         mov      ramdisk_size,eax
  696.         neg      eax
  697.         add      eax,@@end_of_physmem
  698.         and      ax,0f000h     ; round down to full page boundary
  699.         mov      ramdisk_image,eax
  700.         movzx    eax,kernel_size
  701.         add      ax,0ffh
  702.         mov      al,0          ; round up to page boundary
  703.         shl      eax,4         ; size of compressed kernel
  704.         mov      ecx,eax
  705.         shl      eax,1         ; estimated size of decompressed kernel
  706.                                ; (we assume a decompression rate of 1:2)
  707.         sub      ecx,(90000h - 2000h) ; the low buffer size (for bzimages)
  708.         jb       @@3
  709.         add      eax,ecx       ; add padding
  710. @@3:
  711.         add      eax,(100000h+2000h)   ; (+ gunzip-heap), now we have end of kernel
  712.         cmp      eax,ramdisk_image
  713.         jnb      @@err_mem
  714.                  ; ok we have place
  715.                             ; now loading the kernel
  716.                          ; NOTE: needing EDI for open_new_mapped_block
  717.         mov      edi,ramdisk_image
  718.         call     open_new_mapped_block      ; open the first block
  719.         mov      bx,fhandle
  720.         mov      ecx,ramdisk_size
  721.         mov      print_dots,3
  722.         call     read_handle   ; read the ramdisk
  723.         call     print_crlf
  724.         mov      print_dots,0
  725.         call     print_crlf
  726.         jc       @@err_io
  727.         cmp      eax,ecx
  728.         jnz      @@err_io
  729.                            ; ok, all is read into memory
  730.         DosCall  DOS_CLOSE_FILE
  731.         popad
  732. @@ex:
  733.         ret
  734. @@err:
  735.         popad
  736.         mov     dx,@@errtx_addr
  737.         call    print
  738.         jmp     exit_to_dos
  739. @@err_open:
  740.         mov     @@errtx_addr,offset @@tx
  741.         jmp     @@err
  742. @@err_mem:
  743.         mov     @@errtx_addr,offset @@txmem
  744.         jmp     @@err
  745. @@err_io:
  746.         mov     @@errtx_addr,offset @@txio
  747.         jmp     @@err
  748. @@err_unable:
  749.         mov     @@errtx_addr,offset @@txno
  750.         jmp     @@err
  751. @@end_of_physmem dd  0
  752. @@tx    db      13,10,"can't open image file for initrd",13,10,'$'
  753. @@txmem db      13,10,"no place after kernel for initrd",13,10,'$'
  754. @@txio  db      13,10,"IO-error while reading initrd",13,10,'$'
  755. @@txno  db      13,10,"no support in setup for reading initrd",13,10,'$'
  756. @@errtx_addr dw      0
  757. load_initrd endp
  758.  
  759. get_filesize proc near
  760. ; input:
  761. ;   bx = filehandle
  762. ; output:
  763. ;   eax = filesize, all other registers reserved
  764.         push_   cx,dx,esi
  765.         mov     ax,4201h    ; seek to current position
  766.         xor     cx,cx
  767.         xor     dx,dx
  768.         DosInt              ; ... and return current position in DX:AX
  769.         push_   ax,dx       ; save it
  770.         mov     ax,4202h    ; seek to last position
  771.         xor     cx,cx
  772.         xor     dx,dx
  773.         DosInt              ; ... and return EOF position in DX:AX
  774.         mov     si,dx
  775.         shl     esi,16
  776.         mov     si,ax
  777.         pop_    dx,cx
  778.         mov     ax,4200h    ; seek to saved position
  779.         DosInt
  780.         mov     eax,esi
  781.         pop_    cx,dx,esi
  782.         ret
  783. get_filesize endp
  784.  
  785.