home *** CD-ROM | disk | FTP | other *** search
/ Boot Disc 15 / boot-disc-1997-11.iso / Debian / Tools / LODLIN16.ZIP / LODLIN16 / SRC / LOADLIN.ASM next >
Assembly Source File  |  1996-04-28  |  60KB  |  1,659 lines

  1. TESTX = 0
  2. LOADLIN_VERSION equ '1.6'
  3.  
  4. ;   >>> this is file LOADLIN.ASM
  5. ;============================================================================
  6. ;   LOADLIN v1.6 (C) 1994..1996 Hans Lermen (lermen@elserv.ffm.fgan.de)
  7. ;
  8. ;   This program is free software; you can redistribute it and/or modify
  9. ;   it under the terms of the GNU General Public License as published by
  10. ;   the Free Software Foundation; either version 2 of the License, or
  11. ;   (at your option) any later version.
  12. ;
  13. ;   This program is distributed in the hope that it will be useful,
  14. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. ;   GNU General Public License for more details.
  17. ;
  18. ;   You should have received a copy of the GNU General Public License
  19. ;   along with this program; if not, write to the Free Software
  20. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21. ;
  22. ;----------------------------------------------------------------------------
  23. ;   Comments and bug reports are welcome and may be sent to:
  24. ;   E-Mail:    lermen@elserv.ffm.fgan.de
  25. ;   SnailMail: Hans Lermen
  26. ;              Am Muehlenweg 38
  27. ;              D53424 REMAGEN-Unkelbach
  28. ;              GERMANY
  29. ;
  30. ;============================================================================
  31. ;
  32. ; NOTE:
  33. ;
  34. ;   This program could not have been written as quickly without
  35. ;   the information found in the source code of F.Coutant's BOOTLIN
  36. ;
  37. ;   This program contains some modified source code from
  38. ;   my protected mode extender (LDOSX (C) 1991..1994 H.Lermen),
  39. ;   which was written as a fast multitasking alternative
  40. ;   to DJ.Delorie's extender (it runs DJ-GCC compiled binaries under DOS).
  41. ;
  42. ;   I was too lazy to reprogram the subroutines completely, so,
  43. ;   if You wonder what nonsense they are doing, keep in mind that they
  44. ;   were written for an other purpose.
  45. ;
  46. ;============================================================================
  47. ;
  48. ; Contributions and bug fixes for 1.5:
  49. ;
  50. ;
  51. ;   Javier Achirica <javier@autom.uva.es>
  52. ;
  53. ;       invented the switch-out-of-setup method (Javier's method),
  54. ;       which makes the BIOSINTV and REALBIOS method superfluous on nearly
  55. ;       all machines. The trick is: let setup run in V86 and intercept
  56. ;       just before going to protected mode.
  57. ;       (Thank you Javier for this very good work).
  58. ;
  59. ; Contributions for 1.6:
  60. ;
  61. ;   Werner Almesberger <almesber@lrc.epfl.ch>
  62. ;
  63. ;       Werner and me cooperated in realizing high loading of the kernel
  64. ;       and preloading the RAMdisk.
  65. ;       The changes needed in setup.S for both, LILO and LOADLIN,
  66. ;       are a common work of us.
  67. ;       Also the needed kernel patches are the fruits of a very fertile
  68. ;       cooperation. The changes to LILO-1.8 as well as to LOADLIN-1.6
  69. ;       have been developed 'synchroniously' in order to let the whole
  70. ;       Linux community participate on the new boot features.
  71. ;
  72. ;============================================================================
  73.  
  74.               name    load_linux
  75.               .386
  76.               locals
  77.               jumps
  78.  
  79. REALBIOS_FILE equ 'C:\REALBIOS.INT'
  80.  
  81. SIGNATURE                = 'SrdH' ; "HdrS"
  82.  
  83. space4k                  =     1000h
  84. space2k                  =      800h
  85. space1k                  =      400h
  86.  
  87. our_stacksize            =     space2k
  88.  
  89. kernel_start_ equ     01000h     ; here the kernel must go
  90. kernel_end    equ     09000h
  91. standard_setup_sects  equ 4      ; number of setup sectors, older kernels
  92. maximum_setup_sects   equ (32-1) ; max number of setup sectors for newer kernels
  93. High_Seg_     equ     kernel_end  ; here first 512 + 4*512 + n*512 bytes of image must go
  94. High_Addr_    equ     (High_Seg_*16)
  95.  
  96. setup_intercept_int equ   7fh
  97.  
  98.  
  99. debug_stop macro marker
  100.            mov   ax,0b800h
  101.            mov   ds,ax
  102.            mov   byte ptr ds:[1],70h
  103.            mov   byte ptr ds:[0],marker
  104.            jmp   short $
  105.            endm
  106.  
  107. align_  macro   start,val
  108.         org     (((($-start)+(val-1))/val)*val)
  109.         endm
  110.  
  111.  
  112. psp_seg segment  at 0 use16
  113.  
  114. ; -------------PSP Program Segment Prefix----------------------
  115.         org      2h
  116.   PSP_memend_frame            dw ?
  117.         org      2ch
  118.   PSP_envir_frame             dw ?
  119.         org      80h
  120.   PSP_DTA                     db ? (100h-80h) dup(?)
  121. ; -------------------------------------------------------------
  122. psp_seg ends
  123.  
  124. code    segment  para use16
  125.         assume   cs:code,ds:psp_seg,es:code
  126. code_org0     label   byte
  127.  
  128. ; ---------------------------------------------------------------------
  129. ;                        Bootsector (512 bytes)
  130. ;                        within this BEFORE start of setup:
  131. ;                        (may be set by "LOADLIN")
  132. bootsec       label   byte
  133.               org     20h
  134. CL_MAGIC      dw      ?  ;0020   commandline magic number (=0xA33F)
  135. CL_OFFSET     dw      ?  ;0022   commandline offset
  136.                          ; Address of commandline is calculated:
  137.                          ;   0x90000 + contents of CL_OFFSET
  138.                          ; The command line is parsed by "init/main.c"
  139.                          ; Value of NAME=XXXX are put into the environement
  140.                          ; and can then be interpreted by the drivers
  141.                          ; and /etc/rc. The variabel "root=xxxx" is
  142.                          ; interpreted by main directly, "single" is
  143.                          ; interpreted by init or simpleinit.
  144.               org     1F1h
  145. setup_sects   db      ?  ; no. of sectors
  146. ro_flag       dw      ?  ; =0: root file system should be mounted read-write
  147.                          ;<>0: root file system should be mounted readonly
  148.                          ; (this will be overwritten by the kernel commandline
  149.                          ;  options "ro" / "rw")
  150. ;             --------------------------------
  151. ;                        within this AFTER setup has run:
  152.               org     0
  153. curr_curs     dw      ?  ;0000 saved cursor position
  154. ext_mem_size  dw      ?  ;0002     extended memory size in Kb (from int 0x15)
  155.               org     80h
  156. hd0_disk_par  label   byte ;080     hd0-disk-parameter from intvector 0x41
  157. hd1_disk_par  label   byte ;090     hd1-disk-parameter from intvector 0x46
  158.  
  159. ;             --------------------------------
  160. ;                        within this as loaded from "zImage"
  161.               org     01F4h
  162. kernel_size   dw      ?  ; size of kernel-part in the image-file
  163.                          ; (in 16 byte units, rounded up)
  164. swap_dev      dw      ?  ; swap device
  165.  
  166. ram_disk      dw      ?  ;01F8 size of ram-disk (in 1Kb units ) or ZERO
  167.                          ; if ram_disk is nonZERO then the kernel
  168.                          ; (driver/block/ramdisk.c: rd_load() )
  169.                          ; will try to load the contents for the ram-disk
  170.                          ; from the "root_dev" which MUST then have the
  171.                          ; floppyMAJOR.
  172.                          ; The file-system on that floppy must be MINIX
  173.                          ; If rd_load() succeeds it sets the root_dev
  174.                          ; to the ramdisk for mounting it.
  175.                          ;
  176.                          ; LOADLIN parses the commandline for the string
  177.                          ; "ramdisk=nnn" where nnn is the value for "ram_disk"
  178.                          ; after the kernel images has been loaded by LOADLIN
  179.                          ; it asks for inserting the floppy.
  180.                          ; (NOTE: You may have LOADLIN in A: and root_dev in B:
  181.                          ;        or vice versa).
  182.  
  183. vga_mode      dw      ?  ;01FA VGA-Mode
  184.                          ;      -3 = ask
  185.                          ;      -2 = Extended VGA
  186.                          ;      -1 = Normal VGA
  187.                          ;       0 = as "0" was pressed
  188.                          ;       n = as "n" was pressed
  189.                          ;
  190.                          ; LOADLIN parses the commandline for the string
  191.                          ; "vga=nnn" where nnn is the value for "vga_mode"
  192.                          ; it also excepts:
  193.                          ; "vga=ask","vga=normal",'vga=extended"
  194.  
  195. root_dev      dw      ?  ;01FC Root Device (high=Major, low=minor)
  196.                          ;(this can be overwritten by the kernel commandline
  197.                          ; option "root=XXXX")
  198. bootmagic     dw      ?  ;01FE Bootsector magic (0AA55h)
  199.  
  200. ; -------------------------------------------------------------------
  201.                          ; this area will be used to pass params
  202.                          ; from LOADLINX to LOADLIN, if the params file name is @@loadlinx@@ switch
  203.                          ;
  204.                          ; NOTE: '@@loadlinx@@' or '@@loadliXXXX'
  205.                          ;       must NOT be used,
  206.                          ;       if starting LOADLIN without LOADLINX or ULOADLIN
  207.               org     0200h
  208. params_from_loadlinX label byte
  209.  
  210.  
  211. ; -------------------------------------------------------------------
  212.               org     0200h
  213. setup_prog    label   byte
  214.                                     ; the setup-program itself
  215.                                     ; must be started at 9020h:0 !!!
  216.                                     ;                    =======
  217.               jmp     short start_of_setup
  218.                                     ; the setup header
  219.                                     ; (if you have applied the setup.S patch,
  220.                                     ;  or later, if we have it in the standard kernel)
  221. setup_header_sign     dd    ?
  222. setup_header_version  dw    ?
  223. setup_realmode_switch dd    ?
  224. start_sys_seg         dw    ?
  225. kernel_version        dw    ?
  226.                                     ; end of v1.5-header
  227.                                     ; NOTE: above part of header is compatible
  228.                                     ;       with loadlin-1.5 (header v1.5),
  229.                                     ;       must not change it
  230.  
  231. type_of_loader        db   0        ; = 0, old one (LILO, Loadlin,
  232.                                     ;      Bootlin, SYSLX, bootsect...)
  233.                                     ; else it is set by the loader:
  234.                                     ; 0xTV: T=0 for LILO
  235.                                     ;       T=1 for Loadlin
  236.                                     ;       T=2 for bootsect-loader
  237.                                     ;       V = version
  238. loadflags             db   0        ; unused bits =0
  239.                                     ; (reserved for future development)
  240. LOADED_HIGH           =    1        ; bit within loadflags,
  241.                                     ; if set, then the kernel is loaded high
  242. CAN_USE_HEAP          =   80h       ; if set, the loader also has set heap_end_ptr
  243.                                     ; to tell how much space behind setup.S
  244.                                     ; can be used for heap purposes.
  245.                                     ; Only the loader knows what is free!
  246. setup_move_size       dw  8000h     ; size to move, when we (setup) are not
  247.                                     ; loaded at 0x90000. We will move ourselves
  248.                                     ; to 0x90000 then just before jumping into
  249.                                     ; the kernel. However, only the loader
  250.                                     ; know how much of data behind us also needs
  251.                                     ; to be loaded.
  252. code32_start          dd  1000h     ; here loaders can put a different
  253.                                     ; start address for 32-bit code.
  254.                                     ;   0x1000 = default for zImage
  255.                                     ; 0x100000 = default for big kernel
  256. ramdisk_image         dd  0         ; address of loaded ramdisk image
  257.                                     ; Here the loader (or kernel generator) puts
  258.                                     ; the 32-bit address were it loaded the image.
  259.                                     ; This only will be interpreted by the kernel.
  260. ramdisk_size          dd  0         ; it's size in bytes
  261. bootsect_kludge       dd  0         ; pointing to boot_sect_helper
  262. heap_end_ptr          dw  0         ; pointing to end of setup loacal heap.
  263.                                     ; Space from here (exclusive) down to
  264.                                     ; end of setup code can be used by setup
  265.                                     ; for loacal heap purposes.
  266.                   ; ---- end of v2.0 setup-header --------------------
  267.  
  268. start_of_setup:
  269.               org     setup_prog
  270.               db      maximum_setup_sects*512 dup(?)
  271. ; -------------------------------------------------------------
  272. ; the following layout is private to LOADLIN.EXE :
  273.  
  274.                 align_ code_org0,4096
  275. end_of_setup_buffer label byte
  276.  
  277. pagedir         dd    2 dup(0)  ; must be aligned to 4 K
  278.                                 ; NOTE: we have only 1 (one) pagetable, so we
  279.                                 ;       need only 1 pagedir entry
  280.                                 ;       All current known CPUs (386,486,PENTIUM)
  281.                                 ;       tolerate the garbage behind this,
  282.                                 ;       as long as there is no access > 4MB.
  283.                                 ;       So we may overlap the pagedir with
  284.                                 ;       our code
  285.  
  286.     ; ----------------------------v
  287.     ; the following are the params we have to pass to 32-bit adjustemt code
  288. pageadjlist_ptr  dd    (High_Seg_*16) + (pageadjlist-code_org0)
  289. real_32_startup  dd    1000h
  290.     ; ----------------------------^
  291. ; -------------------------------------------------------------
  292.                 align_ code_org0,16
  293. ;                org    02010h
  294. startup_32:
  295.                 ; here we insert the GCC compiled 32-bit code part
  296.                 ; it will be our point to start Linux
  297.                 ; it's current address is 0x94010
  298.                 ;            CHECKIT------^^^^^^^ !!!
  299. IF 1
  300.      INCLUDE PGADJUST.ASM
  301. ELSE
  302.      INCLUDE PGADJTES.ASM
  303. ENDIF
  304. ; -------------------------------------------------------------
  305.  
  306.  
  307. PSP_frame       dw    0  ; our psp
  308. fhandle         dw    0  ; file handle of imagefile
  309. kernel_start    dw    0  ; place were the kernel must at time of
  310.                          ; start of setup
  311. free_mem_start  dw    0  ; frame of free memory, starting at the begin of LOADLIN.EXE
  312. kernel_load_frame dw  0  ; where to load the image
  313.  
  314.                          ; The following (High_Seg,High_Addr)
  315.                          ; will be set to lower values, if we have setup v2.0
  316.                          ; _and_ if 9000 is occupied (W95+DRVSPACE)
  317. High_Seg        dw    kernel_end ; here first 512 + 4*512 + n*512 bytes of image must go
  318. ;spaeter, damit syntaxfehler enstehen:  High_Addr       dd    (High_Seg_*16)
  319.  
  320.     ; ----------------------------v
  321.     ; the following values are cleared on each call to "parscommandline"
  322.     ; (see "clear_to_default")
  323. parse_switches  label byte
  324. new_setup_size  dw    0
  325. new_vga_mode    dw    0
  326. new_ram_disk    dw    0
  327. cl_pointer      dw    0  ; while parsing: aux pointer to command_line
  328. got_vga_mode    db    0
  329. got_ram_disk    db    0
  330. option_v        db    0
  331. option_t        db    0
  332. option_t_forced db    0
  333. option_realbios db    0
  334. option_rx       db    0
  335. option_ja       db    0
  336. option_clone    db    0
  337. option_oldxd    db    0
  338. option_n        db    0
  339. option_nodiskprompt db 0
  340. option_force    db    0
  341. option_initrd   db    0
  342. option_noheap   db    0
  343. intv_size       dw    0
  344. option_wait     dw    0
  345. option_dskreset db    0
  346. wrong_realbios  db    0
  347. have_to_force_realmode db 0 ; 0 = is in realmode
  348.                             ; 1 = is in V86, have to reenter realmode before
  349.                             ;     kernel goes to protected mode
  350.                             ;
  351. have_to_intercept_setup db 0; 0 = old method, no interception
  352.                             ; 1 = intercept boot/setup.S (Javier's method)
  353.                             ;     of older kernels just before going to
  354.                             ;     protected mode.
  355.                             ; 2 = same as 1, but intercepting newer kernels
  356.                             ;     with the setup.dif patch applied.
  357.                             ;
  358.  
  359. debug_file_handle dw    0  ; set to file handle if option -d is set
  360. logo_out        db    0
  361. kernelversion   dd    0     ; binary kernel version, decoded from
  362.                             ; the version string as follows:
  363.                             ; "1.2.3 (root@...) #4" becomes 01020304h
  364.                             ; if string is only 1.2.3  ---> #0 is assumed
  365. token_count     db    0
  366. end_of_physmem  dd    0
  367. parse_switches_end label byte
  368.     ; ----------------------------^
  369.  
  370. can_exit_to_dos db    0
  371. have_VCPI       db    0
  372. have_big_kernel db    0
  373. have_relocated_setup db  0
  374. cannot_load_because_of_windows db 0
  375. print_dots      db    0
  376. cpu_check_status dw   0
  377. setup_version    dw   0       ; =0, if old setup
  378.                               ; else contents of setup_header_version
  379.  
  380.  
  381. ;--------------------higmem stuff -----v
  382. xms_entry dd      0
  383. xms_avail dw      0
  384. xms_handle dw      0
  385. xms_phys_addr dd   0
  386.  
  387. pblock  struc
  388.   taddr  DD   ? ; linear address where the block of pages
  389.                 ; must be moved to
  390.   tstart DW   ? ; index within sources of first entry
  391.   tcount DW   ? ; number of entries for taddr in sources
  392. pblock  ends
  393.  
  394. pages_list struc
  395.   ncount    DD     ?       ; number of entries in 'sources'
  396.   number_of_blocks DD ?    ; number of valid blocks-items
  397.   auxbuf    DD     ?       ; address of 4096 bytes auxiliary buffer
  398.   blocks    pblock 4 dup(?)
  399.   sources   DD     1024 dup (?) ; list of addresses where the block of pages
  400.                                 ; currently _is_ located
  401. pages_list ends
  402.  
  403.  
  404.  
  405. need_mapped_put_buffer db  0
  406. do_mapped_put_buffer db  0    ; 1, if need high load over pagemap
  407.  
  408. load_buffer_size dd   0
  409. heap_ptr       dd     0
  410. heap_end       dd     0
  411. high_heap_ptr  dd     0
  412. heap_max_pages dd     0
  413.  
  414. move_anywhere  dw     move_simple   ; this routine gets called
  415.                                     ; when needing to move buffers
  416.  
  417. high_mem_access db     0     ; = 0, if nothing available
  418. USING_VCPI     =      1
  419. USING_INT15    =      2
  420. USING_XMS      =      3
  421.  
  422.  
  423. ;-----------------------------^
  424. ;NOTE: all uninitialized data has been moved to end of modul
  425. ;      since version 1.4
  426.  
  427. ; -------------------------------------------------------------
  428.  
  429.  
  430.   _DEALLOCATE_PAGES          = 45h;
  431.   _GET_VERSION               = 46h;
  432.   _ALLOCATE_RAW_PAGES        = 5A01H
  433.   EMM_int                    = 67h;
  434.  
  435.  
  436.  
  437.   descript    struc
  438.     limit     dw    ?
  439.     base0     dw    ?
  440.     base16    db    ?
  441.     typbyte   db    ?
  442.     limit16   db    ?
  443.     base24    db    ?
  444.   descript    ends
  445.  
  446.  
  447.   Gdescript struc
  448.     gateoffs0    dw      ?
  449.     gateselector dw      ?
  450.     gatenotused  db      ?
  451.     gatetyppbyte db      ?
  452.     gateoffs16   dw      ?
  453.   Gdescript ends
  454.  
  455.  
  456.   ; definition of COMMON decriptor types (bit0..4 of descript.typbyte )
  457.   ; (bit 4 of descript.typbyte =0)
  458.   data_d        =     10000b    ; data segment descriptor
  459.     writable    =     00010b    ; =1 if write acces allowed to data segment
  460.     expand_down =     00100b    ; =1 limit counts down from base
  461.   code_d        =     11000b    ; code segment
  462.     readable    =     00010b    ; =1 if code also can be read (cannot be ovwritten)
  463.     conforming  =     00100b    ; =1 code can be accesses and executed
  464.                                 ;    regardless of it's privilege level
  465.  
  466.   ; definition of SYSTEM decriptor types  (bit0..4 of descript.typbyte )
  467.   ; (bit 4 of descript.typbyte =0)
  468.   TSS286_avail_d   =  01h
  469.   LDT_d            =  02h
  470.   TSS286_busy_d    =  03h
  471.   call_gate_d      =  04h
  472.   task_gate_d      =  05h
  473.   INT286_gate_d    =  06h
  474.   TRAP286_gate_d   =  07h
  475.   TSS386_avail_d   =  09h
  476.   TSS386_busy_d    =  0bh
  477.   call386_gate_d   =  0ch
  478.   INT386_gate_d    =  0eh
  479.   TRAP386_gate_d   =  0fh
  480.  
  481.   ; definition of privilege levels (bit5..6 of descript.typbyte )
  482.   p0               =  0      ;┐
  483.   p1               =  1*32   ;├ super visor levels
  484.   p2               =  2*32   ;┘
  485.   puser            =  3*32
  486.  
  487.  
  488.   ;definition of granularity ( bits7..8 in descript.limit16 )
  489.   gran_byte        =  0
  490.   gran_page        =  10000000b  ; 4k granularity
  491.   ; for data_selectors:
  492.   data_USE16       =  0
  493.   gran_big         =  01000000b  ; big segment
  494.   data_USE32       =  gran_big   ; use 32-bit stack pointer ESP instead of SP
  495.   ;                Intel says: relevant only together with expand_down  for data_d
  496.   ;                But that is WRONG :
  497.   ;                BIG segment must be set also if the descriptor is greater 64K
  498.   ;                and is used to load SS !
  499.   ;                (because SP cannot access behind 64K)
  500.   ;
  501.   ; for code_selectors:
  502.   code_USE32       =  01000000b  ; default operand size 32 bit (for code segments)
  503.   code_USE16       =  00000000b  ; default operand size 16 bit (for code segments)
  504.  
  505.  
  506.   ; segment present bit (bit7 of descript.typbyte )
  507.   is_present       =128
  508.   not_present      =0
  509.  
  510.   descriptor macro name,typ,plevel,present,limit,gran,base
  511.   name descript <limit and 0ffffh,base and 0ffffh,low (base shr 16),typ or plevel or present,(limit shr 16) or gran,high (base shr 16)>
  512.             endm
  513.  
  514.  
  515.   ;GDT Global Descriptor Table -------------------------v
  516.              align_  code_org0,16
  517.   gdtnull    descript  <?>    ;0000   never accessable
  518.   gdtvcpi_code descript <?>   ;0008
  519.   gdtvcpi2   descript  <?>    ;0010
  520.   gdtvcpi3   descript  <?>    ;0018
  521.   descriptor gdt_core,(data_d+writable),p0,is_present,0fffffh,(gran_page+data_USE32),0
  522.   descriptor gdt_code,(code_d+readable),p0,is_present,0ffffh,(gran_byte+code_USE16),High_Addr_
  523.   descriptor gdt_data,(data_d+writable),p0,is_present,0ffffh,(gran_byte+data_USE16),High_Addr_
  524.   descriptor gdt_ldt,LDT_d,p0,is_present,7,gran_byte,(High_Addr_+(ldtnull-code_org0))
  525.   descriptor gdt_tss,TSS286_avail_d,p0,is_present,0ffh,gran_byte,(High_Addr_+(our_tss-code_org0))
  526.   gdtlast    descript  <?>    ; dummy for addressing
  527.  
  528.   g_vcpi_code equ      (gdtvcpi_code-gdtnull)
  529.   g_core     equ       (gdt_core-gdtnull)
  530.   g_code     equ       (gdt_code-gdtnull)
  531.   g_data     equ       (gdt_data-gdtnull)
  532.   g_ldt      equ       (gdt_ldt-gdtnull)
  533.   g_tss      equ       (gdt_tss-gdtnull)
  534.   ;GDT Global Descriptor Table -------------------------^
  535.  
  536.  
  537.   ;LDT Local  Descriptor Table -------------------------v
  538.   ldtnull    descript  <?>    ;0000   never accessable
  539.   ldtlast    descript  <?>    ; dummy for addressing
  540.   ;LDT Local  Descriptor Table -------------------------^
  541.  
  542.   ;                  align_  SYSTEMDATA_,1024
  543.   ;IDT Interrupt Descriptor Table -------------------------v
  544.   idtnull    descript  32 dup (<0>)
  545.   idtlast    descript  <?>    ; dummy for addressing
  546.   ;IDT Interrupt Descriptor Table -------------------------^
  547.  
  548.   our_tss    dd        128 dup (?)    ; our TSS Task State Segment
  549.  
  550.  
  551.   ;params for switching TO protected mode -------------------------v
  552.                           ;NOTE: this Data MUST be in LOW_MEM (below 1 Mbyte),
  553.                           ;      data referenced by this structure
  554.                           ;      CAN be in memory above 1 Mbyte
  555.                           ;      On switching to protected mode the server
  556.                           ;      first loads CR3 (paging base) from "our_CR3".
  557.                           ;
  558.                         ; value of CR3 to be loaded by server
  559.     our_CR3    dd       (High_Addr_+(pagedir-code_org0))
  560.                         ; linear address in first Mbyte pointing to
  561.                         ; value of GDTR ("our_GDTR") to be loaded by server
  562.     our_GDTRptr dd      (High_Addr_+(our_GDTR-code_org0))
  563.                         ; linear address in first Mbyte pointing to
  564.                         ; value of IDTR ("our_IDTR") to be loaded by server
  565.     our_IDTRptr dd      (High_Addr_+(our_IDTR-code_org0))
  566.                         ; value of LDTR to be loaded by server
  567.     our_LDTR   dw       g_ldt
  568.                         ; value of TR to be loaded by server
  569.     our_TR     dw       g_tss
  570.                         ; Fword, pointer to code to be started by server
  571.     protected_mode_target DD ?
  572.                           DW g_code
  573.   ;  belongs to above
  574.     our_GDTR   dw       (gdtlast-gdtnull)-1    ;limit (byte gran)
  575.                         ;linear (not physical) base address of "gdtnull"
  576.     laddr_GDT  dd       (High_Addr_+(gdtnull-code_org0))
  577.                dw       ?    ; (just for align "laddr_IDT" to Dword)
  578.     our_IDTR   dw       (idtlast-idtnull)-1    ;limit (byte gran)
  579.                         ;linear (not physical) base address of "Idtnull"
  580.     laddr_IDT  dd       (High_Addr_+(idtnull-code_org0))
  581.   ;-------------------------------------------------------------------^
  582.  
  583.   server_vcpi_entry df  0 ; this is the address we must call instead of INT67
  584.                           ; when in protected mode
  585.   pagedir_template dd     (High_Addr_+(page0-code_org0)+3)
  586.  
  587.  
  588.  
  589. ;=============================================================================
  590.  
  591.  
  592. DOS_WRITE_STRING        = 009h ; Display a '$' terminated string
  593. DOS_BUFFERED_INPUT      = 00Ah ; Read text and store it in a buffer
  594. DOS_OPEN_FILE           = 03Dh ; Open an existing file
  595. DOS_CREATE_FILE         = 03Ch ; create a new file
  596. DOS_CLOSE_FILE          = 03Eh ; Close a file
  597. DOS_READ_FROM_HANDLE    = 03Fh ; Read from DOS file handle
  598. DOS_WRITE_TO_HANDLE     = 040h ; write to DOS file handle
  599. DOS_TERMINATE_EXE       = 04Ch ; Terminate program
  600.  
  601. DosCall macro function_code
  602.     mov ah,function_code
  603.     int 21h
  604. endm
  605. DosInt macro
  606.     int 21h
  607. endm
  608.  
  609.  
  610.  
  611. push_ macro r1,r2,r3,r4,r5,r6,r7,r8,rx
  612.            irp   parm,<&r1,&r2,&r3,&r4,&r5,&r6,&r7,&r8,&rx>
  613.              ifndef parm
  614.                exitm
  615.              endif
  616.              push parm
  617.            endm
  618.          endm
  619. pop_  macro r1,r2,r3,r4,r5,r6,r7,r8
  620.            irp   parm,<&r8,&r7,&r6,&r5,&r4,&r3,&r2,&r1>
  621.              ifdef parm
  622.                pop parm
  623.              endif
  624.            endm
  625.          endm
  626.  
  627. pushAD_struc macro prefix
  628.            irp   parm,<edi,esi,ebp,esp,ebx,edx,ecx,eax>
  629.              prefix&&parm  dd  ?
  630.            endm
  631.          endm
  632.  
  633. pushA_struc macro prefix
  634.            irp   parm,<di,si,bp,sp,bx,dx,cx,ax>
  635.              prefix&&parm  dw  ?
  636.            endm
  637.          endm
  638.  
  639.  
  640. cpu_86     equ   0
  641. cpu_286    equ   2
  642. cpu_386V86 equ   3       ; is >=386, but in virtual 86 mode
  643. cpu_386GE  equ   4       ; >=386
  644. cpu_386GE_real_paging equ 5
  645. cpu_type   dw    0
  646.  
  647. cpu_check proc near
  648.         pushf
  649.         cmp     option_force,0
  650.         jnz     is_force_386GE
  651.         xor     ax,ax   ;0000 to ax
  652.         push    ax
  653.         popf            ; try to put that in flags
  654.         pushf
  655.         pop     ax      ; look at what really went into flags
  656.         and     ah,0f0h ; mask off high flag bits
  657.         cmp     ah,0f0h
  658.         je      is_8086
  659.         mov     ax,0f000h
  660.         push    ax      ; try to set the high bits
  661.         popf
  662.         pushf
  663.         pop     ax      ; look at actual flags
  664.         and     ah,0f0h
  665.         je      is_80286
  666.                         ; is x86, x >= 3
  667.                         ; check for V86 or real-paging -mode
  668.         mov     ah,040h ; try to clear IOPL
  669.         push    ax
  670.         popf
  671.         pushf
  672.         pop     ax
  673.         and     ah,030h
  674.         jne     is_v86
  675.         cmp     option_clone,0
  676.         jnz     @@clone
  677.         .386p
  678.         mov     eax,cr0        ; normally this would cause a GP(0)-exception
  679.                                ; (i386 Programmers Reference Guide, INTEL 1987)
  680.                                ; if in V86-mode, but most EMMXXXX drivers
  681.                                ; seem to intercept this exception and allow
  682.                                ; reading the CR0.
  683.         .386
  684.         or      eax,eax
  685.         jz      is_v86         ; not a valid CR0, reserved bits are allways set
  686.                                ; (this may be not true on a 486 clone such as
  687.                                ;  the 486DLC, so if you have trouble with
  688.                                ;  interpreting real mode as V86 use the -clone switch
  689.                                ;
  690.         test    al,01h         ; test PE -bit
  691.         jz      is_greater_equal_80386
  692. is_v86:
  693.         mov     ax,cpu_386V86
  694. cpu_check_exit:
  695.         mov     cpu_type,ax
  696.         popf
  697.         ret
  698. is_8086:
  699.         mov     ax,cpu_86
  700.         jmp     cpu_check_exit
  701. is_80286:
  702.         mov     ax,cpu_286
  703.         jmp     cpu_check_exit
  704. is_greater_equal_80386:
  705.         test    eax,eax         ; test PG - bit
  706.         js      is_386_real_pageing
  707.         mov     ax,cpu_386GE
  708.         jmp     cpu_check_exit
  709. is_force_386GE:
  710.         mov     ax,cpu_386GE
  711.         jmp     cpu_check_exit
  712. is_386_real_pageing:
  713.         mov     ax,cpu_386GE_real_paging
  714.         jmp     cpu_check_exit
  715.  
  716. @@clone:                 ; on some 486 clones we have problems with CR0,
  717.                          ; so we are looking for EMM, and then
  718.                          ; we assume to be in V86, if we have EMM.
  719.         push    ds
  720.         xor     ax,ax
  721.         mov     ds,ax
  722.         mov     ds,word ptr ds:[emm_int*4+2]
  723.         mov     ax,cpu_386V86
  724.         cmp     dword ptr ds:[10+4],'0XXX'
  725.         jne     @@cl1
  726.         cmp     dword ptr ds:[10],'QMME'
  727.         je      @@clex
  728.         cmp     dword ptr ds:[10],'XMME'
  729.         je      @@clex
  730. @@cl1:
  731.         mov     ax,cpu_386GE
  732. @@clex:
  733.         pop     ds
  734.         jmp     cpu_check_exit
  735.  
  736. cpu_check endp
  737.  
  738. ;=============================================================================
  739.  
  740.  
  741. start:
  742.         .8086    ; we are not sure here if on a 368 CPU
  743.         mov      cs:PSP_frame,es
  744.         mov      ax,cs     ; switch the to our stack
  745.         mov      ss,ax
  746.         lea      sp,stack_top
  747.         mov      ds,ax
  748.         mov      es,ax
  749.         call     clear_uninitialized_data
  750.         mov      ds,cs:PSP_frame
  751.         cld
  752.         lea      si,PSP_DTA+1
  753.         lea      di,comline+1
  754.         mov      cl,PSP_DTA
  755.         xor      ch,ch
  756.         jcxz     start__2
  757. start__:                          ; skip leading blanks
  758.         cmp      byte ptr [si],' '
  759.         jne      start__2
  760.         inc      si
  761.         loop     start__
  762. start__2:
  763.         mov      comline-1,ch
  764.         mov      comline,cl
  765.         inc      cx             ; get the CR too
  766.         rep movsb               ; get the commandline out of psp
  767.  
  768.         push     cs
  769.         pop      ds
  770.         assume   ds:code
  771.                  ; from now on we have CS=DS=ES=SS
  772.  
  773.                  ; make sure that size byte is correct
  774.                  ; ( some DOS versions set only CR .. sometimes )
  775.         lea      di,comline+1
  776.         mov      al,13
  777.         call     strlen
  778.         cmp      al,comline
  779.         jnb      start_0
  780.         mov      comline,al
  781. start_0:
  782.         mov      bx,word ptr comline-1
  783.         xchg     bh,bl
  784.         mov      comline[bx+1],0  ; replace CR by ZERO
  785.  
  786.         mov      logo_out,0
  787.         mov      print_dots,0
  788.  
  789.         mov      kernel_start,kernel_start_ ; real kernel_start
  790.         mov      free_mem_start,cs  ;save CS as later freemem
  791.  
  792.                  ; now check if (on error) we can exit do DOS
  793.         lea      bx,comspec_tx
  794.         call     get_env_variable     ; we expect COMSPEC= in the environement
  795.         mov      al,byte ptr es:[di]
  796.         mov      can_exit_to_dos,al
  797.                  ; check if we are running under windows
  798.         lea      bx,windows_tx
  799.         call     get_env_variable     ; we expect WINDIR= in the environement
  800.         mov      al,byte ptr es:[di]
  801.         mov      cannot_load_because_of_windows,al
  802.         push     ds
  803.         pop      es
  804.  
  805.  
  806.         lea      ax,modul_end+15
  807.         shr      ax,4
  808.         mov      bx,ax
  809.         add      ax,High_Seg
  810.         mov      es,PSP_frame
  811. IF 1
  812.         sub      ax,es:PSP_memend_frame
  813. ELSE ;TEST (to simulate an occupied 90000 segment )
  814. ;        sub      ax,09400h
  815.         sub      ax,05400h
  816. ENDIF
  817.         jb       start_3
  818.                  ; we have the 9000 page occupied by some program
  819.                  ; and we try to move down the setup code below that
  820.                  ; if we later detect an older setup-version,
  821.                  ; we must give up, jumping to "err_uppermem".
  822.         neg      ax
  823.         add      High_Seg,ax
  824.         and      High_Seg,0ff00h  ; allign on next lower page boundary
  825.                                   ; (need this for the pagetables)
  826.         call     relocate_setup_code
  827. start_3:
  828.  
  829.         push     ds
  830.         pop      es                     ; restore es
  831.  
  832.         mov      ax,free_mem_start
  833.         cmp      ax,kernel_start
  834.         jnb      start_9
  835.         mov      ax,kernel_start
  836. start_9:
  837.         mov      kernel_load_frame,ax
  838.  
  839.         mov      token_count,-1
  840.                  ; check if we are on the right CPU
  841.         mov      cpu_check_status,0
  842.         mov      option_clone,1  ; avoid reading CR0 before parsing -clone
  843.         call     cpu_check
  844.         lea      dx,err_wrong_cpu_tx
  845.         cmp      ax,cpu_386V86
  846.         jb       err_print    ; has no 386 or greater at all
  847.  
  848.         .386    ; now we are sure beeing on a 386(and greater) CPU
  849.         cmp      can_exit_to_dos,0
  850.         jnz      m2
  851.         lea      di,comline+1   ; as DOS (stupidly) converts all from
  852.                                 ; CONFIG.SYS to UPPERCASE, we do TOLOWER
  853.         call     tolower
  854. m2:
  855.         call     parscommandline
  856.         call     cpu_check    ; do it once more, because of option_clone
  857.  
  858.         mov      cpu_check_status,2
  859.         call     get_default_bios_intvectors
  860.         cmp      ax,cpu_386GE
  861.         jb       m2_1
  862.         test     intv_size,0fffch
  863.         jnz      start_continue    ; has $BIOSINTV or REALBIOS.INT
  864.         cmp      option_t_forced,0
  865.         jnz      start_continue
  866.         mov      have_to_intercept_setup,1
  867.         jmp      start_continue
  868. m2_1:
  869.         mov      cpu_check_status,4
  870.                               ; have 386, but are in V86-mode
  871.         call     check_VCPI_present
  872.         jz       err_wrong_cpu   ; has no VCPI-server
  873.         mov      have_vcpi,1
  874.         mov      cpu_check_status,6
  875.         call     check_low_mem_mapping
  876.         jz       err_wrong_cpu   ; has no identical phys/log mapping
  877.         mov      have_to_force_realmode,1
  878.         test     intv_size,0fffch
  879.         jnz      plain_switch    ; has $BIOSINTV or REALBIOS.INT
  880.                                  ; has no $BIOSINTV driver loaded
  881.                                  ; but will try to start Linux anyway
  882.         cmp      option_t_forced,0
  883.         jnz      plain_switch
  884.         mov      word ptr cs:intv_buf+(4*15h+2),0
  885.         mov      have_to_intercept_setup,1
  886. plain_switch:
  887.         mov      cpu_check_status,8
  888.  
  889.  
  890. start_continue:
  891.         cmp      token_count,0
  892.         jg       m3
  893.         jz       start_continue_1
  894.         cmp      comline,0   ; have we an emtpy string ?
  895.         jnz      m3
  896. start_continue_1:
  897.         mov      need_mapped_put_buffer,1 ; | we are doing this to
  898.         call     build_buffer_heap        ; | get the avail mem for printing
  899.         lea      dx,empty_tx
  900.         jmp      err_print
  901.  
  902.                           ; have file-name at minimum
  903.                           ; trying to open it
  904. m3:
  905.         mov      ax,DOS_OPEN_FILE shl 8
  906.         lea      dx,image_name
  907.         DosInt
  908.         jnc      fileopened
  909. m4:
  910.         lea      dx,err_file_notfound_tx
  911. m4_:
  912.         call     print
  913.         lea      dx,enter_commandline_tx
  914.         call     print
  915.         call     readstring
  916.         cmp      comline,0   ; have we an emtpy string ?
  917.         jnz      m2
  918.         lea      dx,abort_tx
  919.         call     print
  920.         jmp      err_exit
  921.  
  922. fileopened:
  923.         mov      fhandle,ax
  924. IFNDEF DEBUG
  925.         ;---------------------------------------
  926.         mov      ax,High_Seg   ; move us high
  927.         mov      es,ax
  928.         push     cs
  929.         pop      ds
  930.         xor      si,si
  931.         xor      di,di
  932.         lea      cx,modul_end+3
  933.         shr      cx,2
  934.         rep movsd
  935.         push     es
  936.         pop      ds
  937.                  ; we have move ourself up
  938.                  ; must now change cs
  939.         push     ds
  940.         lea      ax,back_from_low
  941.         push     ax
  942.         retf
  943. back_from_low:
  944.         mov      ax,ds     ; switch the stack to top
  945.         mov      ss,ax
  946.         lea      sp,stack_top
  947. ENDIF
  948.                  ; from now on we have CS=DS=ES=SS=setup_memory
  949.         ;-------------------------------------------
  950.         cmp      have_to_force_realmode,0
  951.         je       back_from_low_continue
  952.                  ; we have to do this once more
  953.                  ; because some VCPI-servers rely on an unmovable page0
  954.         call     get_VCPI_interface
  955.  
  956. back_from_low_continue:
  957.                           ; first look if it is really an image
  958.         mov      bx,fhandle
  959.         mov      ecx,512
  960.         mov      di,cs
  961.         movzx    edi,di
  962.         shl      edi,4
  963.         call     read_handle   ; read the bootsector
  964.         jnc      have_bootsect
  965. fileopened_wrong:
  966.         DosCall  DOS_CLOSE_FILE
  967.         lea      dx,err_wrong_file_tx
  968.         jmp      m4_
  969. err_wrong_setup:
  970.         DosCall  DOS_CLOSE_FILE
  971.         lea      dx,err_wrong_setup_tx
  972.         jmp      m4_
  973. err_setup_too_long:
  974.         DosCall  DOS_CLOSE_FILE
  975.         lea      dx,err_setup_too_long_tx
  976.         jmp      m4_
  977.  
  978. have_bootsect:
  979.         cmp      ax,cx
  980.         jne      fileopened_wrong
  981.         cmp      bootmagic,0AA55h
  982.         jne      fileopened_wrong
  983.                             ; ok, now get the setup part
  984.         mov      di,cs
  985.         lea      bx,setup_prog
  986.         shr      bx,4
  987.         add      di,bx
  988.         mov      bx,fhandle
  989.         xor      ecx,ecx
  990.         mov      ch,setup_sects
  991.         shl      cx,1
  992.         jnz      new_bootsect
  993.         mov      ch,2*standard_setup_sects
  994. new_bootsect:
  995.         cmp      cx,maximum_setup_sects*512
  996.         ja       err_setup_too_long
  997.         mov      new_setup_size,cx
  998.         movzx    edi,di
  999.         shl      edi,4
  1000.         call     read_handle   ; read setup
  1001.         jc       fileopened_wrong
  1002.         cmp      ax,cx
  1003.         jne      fileopened_wrong
  1004.         call     get_setup_version
  1005.         cmp      setup_version,0201h ; do we have to set setup heap ?
  1006.         jb       new_bootsect_3      ; no
  1007.         cmp      option_noheap,0     ; yes, but is it disabled ?
  1008.         jnz      new_bootsect_3      ; yes
  1009.         or       loadflags,CAN_USE_HEAP ;no
  1010.         mov      heap_end_ptr,(end_of_setup_buffer-setup_prog)
  1011. new_bootsect_3:
  1012.  
  1013.                  ; if we have setup-code not at 9000
  1014.                  ; we have to check for  setup-version >= 2.0
  1015.         cmp      High_seg,High_seg_
  1016.         je       have_setup_3  ; no need for version 2.0
  1017.         cmp      word ptr setup_version,0200h
  1018.         jb       err_uppermem ; we can't continue
  1019.                  ; ok, we set the correct move size
  1020.         lea      ax,modul_end
  1021.         mov      setup_move_size,ax
  1022. have_setup_3:
  1023.         mov      ax,High_Seg
  1024.         sub      ax,kernel_load_frame
  1025.         movzx    eax,ax
  1026.         shl      eax,4
  1027.         mov      load_buffer_size,eax
  1028.  
  1029.                  ; if we have setup > 2.0, we set our loader version
  1030.         cmp      setup_version,0200h
  1031.         jb       have_setup_4
  1032.  
  1033. ;@@@@@@@@@@@@@@@@@@@@@
  1034.                  ; well here the new tricky loadling stuff is prepared
  1035.  
  1036.         mov      type_of_loader,10h  ; our loader type + version
  1037.                          ; we tell setup not to start the kernel,
  1038.                          ; but our special 32-bit page-adjust-routine
  1039.         mov      cs:code32_start,(High_Seg_*16) + (startup_32-code_org0)
  1040.                          ; we tell 'read_handle' to use mapped move
  1041.         mov      cs:need_mapped_put_buffer,1
  1042.                          ; we build the two heaps, low and high
  1043.                          ; for this we need to align the low to page boundary
  1044.                          ; align the kernel_load_frame to page boundary
  1045.         mov      ax,kernel_load_frame
  1046.         add      ax,0ffh
  1047.         mov      al,0
  1048.         mov      kernel_load_frame,ax
  1049.         mov      ax,High_Seg
  1050.         sub      ax,kernel_load_frame
  1051.         movzx    eax,ax
  1052.         shl      eax,4
  1053.         mov      load_buffer_size,eax
  1054.         call     build_buffer_heap
  1055.  
  1056.         mov      edi,01000h   ;the address the image must go
  1057.         mov      cs:real_32_startup,edi ; were the kernel gets started
  1058.                          ; we now determin what kind of zImage we have
  1059.         test     cs:loadflags,LOADED_HIGH
  1060.         jz       must_start_low
  1061.         mov      have_big_kernel,1
  1062.         mov      edi,0100000h   ;the address the image must go
  1063.         mov      cs:real_32_startup,edi ; were the kernel gets started
  1064. must_start_low:
  1065.                          ; even if the image starts low,
  1066.                          ; we use the 'high load' routines,
  1067.                          ; so we force this bit in loadflags
  1068.         or       cs:loadflags,LOADED_HIGH
  1069.                          ; NOTE: needing EDI from above for open_new_mapped_block
  1070.         call     open_new_mapped_block      ; open the first block
  1071. ;@@@@@@@@@@@@@@@@@@@@@
  1072.  
  1073. have_setup_4:
  1074.         cmp      have_to_intercept_setup,0
  1075.         jz       dont_patch
  1076.         cmp      dword ptr ds:setup_header_sign,SIGNATURE
  1077.         jnz      not_signed
  1078.         mov      have_to_intercept_setup,2
  1079.         mov      word ptr ds:setup_realmode_switch,offset real_switch
  1080.         mov      ax,High_Seg
  1081.         mov      word ptr ds:setup_realmode_switch+2,ax
  1082.         mov      ax,kernel_load_frame
  1083.         mov      word ptr ds:start_sys_seg,ax
  1084.         jmp      dont_patch
  1085. not_signed:
  1086.         xor      di,di
  1087.         mov      cx,new_setup_size
  1088.         mov      al,0FAh    ; cli
  1089.         cld
  1090. keep_searching:
  1091.         repnz scasb
  1092.         jcxz     err_wrong_setup
  1093.         cmp      dword ptr [di],70E680B0h ; mov al,80h
  1094.                                           ; out 70h,al
  1095.         jnz      keep_searching
  1096.         mov      byte ptr [di-1],0CDh   ; int op code
  1097.         mov      byte ptr [di],setup_intercept_int  ; int number
  1098.         mov      word ptr [di+1],4444h ; inc sp       adjust stack
  1099.                                        ; inc sp       (discard flags)
  1100.         mov      byte ptr [di+3],90h   ; nop
  1101. dont_patch:
  1102.                           ; we convert the kernel version string
  1103.                           ; to a binary number
  1104.         xor      eax,eax
  1105.         cmp      have_to_intercept_setup,2
  1106.         jne      dont_patch_
  1107.         call     get_kernel_version
  1108. dont_patch_:
  1109.         mov      kernelversion,eax
  1110.         call     handle_kernel_specifics
  1111.                           ; ok, now check the size of the kernel
  1112.         movzx    eax,kernel_size
  1113.         shl      eax,4
  1114.         cmp      eax,load_buffer_size
  1115.         jb       have_space
  1116.         lea      dx,err_kernel_to_big_tx
  1117.         cmp      option_t,0
  1118.         je       err_print
  1119.  
  1120. have_space:
  1121.  
  1122.                            ; now we update the params
  1123.         cmp      command_line,0
  1124.         jz       no_comline
  1125.         mov      CL_MAGIC,0A33Fh
  1126.         lea      ax,command_line
  1127.         mov      CL_OFFSET,ax
  1128.         mov      si,cl_pointer
  1129.         mov      byte ptr [si-1],0 ;delete the last blank
  1130.  
  1131.  
  1132. no_comline:
  1133.                            ; check for ramdisk
  1134.         cmp      got_ram_disk,0
  1135.         jz       no_change_on_ramdisk
  1136.         mov      ax,new_ram_disk
  1137.         mov      ram_disk,ax
  1138. no_change_on_ramdisk:
  1139.                            ; check for vga
  1140.         cmp      got_vga_mode,0
  1141.         jz       no_change_on_vga
  1142.         mov      ax,new_vga_mode
  1143.         mov      vga_mode,ax
  1144.  
  1145. no_change_on_vga:
  1146.  
  1147.         cmp      cannot_load_because_of_windows,0
  1148.         jz       no_windows
  1149.         call     force_error_verbose
  1150. no_windows:
  1151.  
  1152.                            ; check for -v option
  1153.         cmp      option_v,0
  1154.         jz       no_option_v
  1155.                            ; option -v (verbose) is set
  1156.                            ; print some information
  1157.         call     print_verbose
  1158.  
  1159. no_option_v:
  1160.                            ; check for -t option
  1161.         cmp      option_t,0
  1162.         jz       no_option_t
  1163.         DosCall  DOS_CLOSE_FILE
  1164.         lea      dx,option_t_terminate_tx
  1165.         cmp      option_t_forced,0
  1166.         jz       no_option_t_forced
  1167.         lea      dx,option_t_forced_tx
  1168. no_option_t_forced:
  1169.         call     print
  1170.         jmp      err_exit
  1171.  
  1172. no_option_t:
  1173.                            ; start of critical section
  1174.                            ; =========================
  1175.         call     close_debug_file
  1176.  
  1177.                             ; now loading the kernel
  1178.         mov      bx,fhandle
  1179.         movzx    ecx,kernel_size
  1180.         shl      ecx,4
  1181.         mov      di,kernel_load_frame
  1182.         movzx    edi,di
  1183.         shl      edi,4
  1184.         mov      print_dots,2
  1185.         call     read_handle   ; read the kernel
  1186.         call     print_crlf
  1187.         mov      print_dots,0
  1188.         call     print_crlf
  1189.         jc       err_io
  1190.         add      eax,15
  1191.         and      al,0f0h
  1192.         cmp      eax,ecx
  1193.         jnz      fileopened_wrong
  1194.                            ; ok, all is read into memory
  1195.         DosCall  DOS_CLOSE_FILE
  1196.  
  1197.         cmp      ram_disk,0 ; have we a ramdisk
  1198.         jz       no_ram_disk
  1199.         cmp      option_nodiskprompt,0;
  1200.         jnz      no_ram_disk
  1201.                            ;we must prompt for insertion of floppy
  1202.         lea      dx,insert_floppy_tx
  1203.         call     print
  1204.         call     readstring    ; just to wait for prompt
  1205. no_ram_disk:
  1206.                  ; now we try to load the initrd ramdisk-image
  1207.         call     load_initrd
  1208.                  ; now we clean up all entries in the page adjust list
  1209.         call     final_page_adjust_list_handling
  1210.                  ; that's it
  1211.  
  1212.                  ; here we handle -wait and -dskreset
  1213.                  ; These option are to avoid outstanding disk-IRQs
  1214.                  ; happen, when Linux tries to detect the hardware.
  1215.                  ; In most cases we will not need this.
  1216.         call     wait_and_reset_dsk
  1217.  
  1218.         cli
  1219. ___go:
  1220.         cmp      have_to_intercept_setup,1
  1221.         ja       ___go_switch
  1222.         je       ___go_skip_move
  1223.         call     move_kernel_down
  1224. ___go_skip_move:
  1225.         cmp      have_to_intercept_setup,1
  1226.         jne      ___go_switch
  1227.         xor      ax,ax
  1228.         mov      ds,ax
  1229.         mov      word ptr ds:[4*setup_intercept_int],offset real_switch
  1230.         mov      word ptr ds:[4*setup_intercept_int+2],cs
  1231. ___go_switch:
  1232.         mov      ax,cs:High_Seg
  1233.         mov      ds,ax
  1234.         mov      es,ax
  1235.  
  1236.         cmp      have_to_intercept_setup,0
  1237.         ja       ___go_continue
  1238.         call     switch_to_protected_mode_and_return_in_386realmode
  1239.  
  1240. ___go_continue:
  1241.         call     restore_bios_default_vectors
  1242.         lea      bx,setup_prog
  1243.         shr      bx,4
  1244.         mov      ax,High_Seg
  1245.         add      ax,bx
  1246.         lea      sp,setup_stack_top  ; separate stack during
  1247.                                      ; setup and real_switch
  1248.         push     ax
  1249.         push     0
  1250.  
  1251.         retf     ; and now it's the job of setup
  1252.                  ; but NOTE:
  1253.                  ;   on have_to_force_realmode >0 setup calls real_switch
  1254.  
  1255. setup_own_stack df 0
  1256.  
  1257.  
  1258. real_switch proc far
  1259.         ;  NOTE:  we have to preserve ALL registers !
  1260.         ;         to avoid conflicts with future kernels
  1261.         cli
  1262.         push_    ds,es,fs,gs
  1263.         pushad
  1264.         mov      al,80h
  1265.         out      [70h],al
  1266.         mov      ax,cs
  1267.         mov      ds,ax
  1268.         mov      es,ax
  1269.         mov      word ptr setup_own_stack+4,ss
  1270.         mov      dword ptr setup_own_stack,esp
  1271.                         ; Ok,ok, today setup has our stack (no need to switch)
  1272.         mov      ss,ax  ; ... but we want to be sure for the future,
  1273.         lea      sp,stack_top ; so we switch to our stack
  1274.         cmp      have_to_intercept_setup,2 ; have we to move the kernel down ?
  1275.         je       @@3  ; no, setup will do it (knows the location of the image)
  1276.                       ; yes, we have patched in the intercept code,
  1277.                       ; so the kernel expects the kernel at 10000h
  1278.         call     move_kernel_down
  1279. @@3:
  1280.         call     switch_to_protected_mode_and_return_in_386realmode
  1281.         lss      esp,cs:setup_own_stack ; restore setup's stack
  1282.         popad
  1283.         pop_     ds,es,fs,gs
  1284.         retf
  1285. real_switch endp
  1286.  
  1287. ;=============================================================================
  1288.  
  1289.  
  1290. move_kernel_down proc near
  1291.                            ; is the kernel at its right place ?
  1292.         cli
  1293.         mov      ax,kernel_start
  1294.         cmp      kernel_load_frame,ax
  1295.         je       short @@ex  ; yes
  1296.                            ; no, must move it down
  1297.         push_    ds,es
  1298.         cld
  1299. mgran = 08000h
  1300.         mov      bp,mgran shr 4
  1301.         mov      ax,kernel_size
  1302.         mov      bx,kernel_start
  1303.         mov      dx,kernel_load_frame
  1304. @@loop:
  1305.         mov      cx,mgran shr 2
  1306.         mov      ds,dx
  1307.         mov      es,bx
  1308.         xor      si,si
  1309.         xor      di,di
  1310.         rep movsd
  1311.         add      bx,bp
  1312.         add      dx,bp
  1313.         sub      ax,bp
  1314.         cmp      ax,bp
  1315.         ja       @@loop
  1316.         mov      cx,ax
  1317.         shl      cx,2
  1318.         mov      ds,dx
  1319.         mov      es,bx
  1320.         xor      si,si
  1321.         xor      di,di
  1322.         rep movsd
  1323.  
  1324.         pop_     ds,es
  1325.         mov      ax,kernel_start
  1326.         mov      kernel_load_frame,ax
  1327. @@ex:
  1328.         ret
  1329. move_kernel_down endp
  1330.  
  1331.  
  1332. err_wrong_cpu:
  1333.         lea      dx,err_cpu_v86_tx
  1334. err_print:
  1335.         cmp      token_count,0
  1336.         jz       err_print_1
  1337.         jg       err_print_2
  1338.         cmp      word ptr comline-1,0   ; have we an command line
  1339.         jnz      err_print_2 ; yes
  1340.                              ; no, print help and status
  1341. err_print_1:
  1342.         push     dx
  1343.         lea      dx,usage_tx
  1344.         call     print
  1345.         pop      dx
  1346. err_print_2:
  1347.         call     print
  1348.         cmp      cpu_type,cpu_386V86
  1349.         jb       err_exit
  1350.         call     print_verbose_stat
  1351.         jmp      err_exit
  1352. err_io:
  1353.         lea      dx,err_io_tx
  1354.         call     print
  1355.         jmp      err_exit
  1356.  
  1357. err_uppermem:
  1358.         lea      dx,err_uppermem_tx
  1359.         call     print
  1360. err_exit:
  1361.         cmp      cs:can_exit_to_dos,0
  1362.         jz       idle
  1363.         mov      al,1
  1364. exit_to_dos:
  1365.         call     free_extended_memory
  1366.         call     close_debug_file
  1367.         DosCall  DOS_TERMINATE_EXE
  1368. idle:
  1369.         lea      dx,err_in_config_sys_tx
  1370.         call     print
  1371.         call     close_debug_file
  1372. idle_:
  1373.         sti
  1374.         jmp      idle_
  1375.  
  1376. real_print   proc    near
  1377. ; input: DX = offset of string within CODE
  1378.         .8086
  1379.         push    ds
  1380.         push    cs
  1381.         pop     ds
  1382.         push_   bx,cx,si
  1383.         mov     si,dx
  1384.         cld
  1385.         xor     ax,ax
  1386. @@loop:
  1387.         lodsb
  1388.         test    ax,ax
  1389.         jz      @@ok
  1390.         cmp     al,'$'
  1391.         jnz     @@loop
  1392. @@ok:
  1393.         dec     si
  1394.         sub     si,dx
  1395.         jz      @@null
  1396.         mov     cx,si
  1397.         mov     bx,1
  1398.         DosCall DOS_WRITE_TO_HANDLE
  1399.         cmp     debug_file_handle,0
  1400.         jz      @@ex
  1401.         mov     bx,debug_file_handle
  1402.         DosCall DOS_WRITE_TO_HANDLE
  1403. @@null:
  1404. @@ex:
  1405.         pop_    bx,cx,si
  1406.         pop     ds
  1407.         ret
  1408.         .386
  1409. real_print   endp
  1410.  
  1411. print proc near
  1412.         cmp      cs:logo_out,0
  1413.         jnz      @@ex
  1414.         mov      cs:logo_out,1
  1415.         push_    ax,dx
  1416.         lea      dx,logo_tx
  1417.         call     real_print
  1418.         pop_      ax,dx
  1419. @@ex:
  1420.         call     real_print
  1421.         ret
  1422. print endp
  1423.  
  1424.  
  1425. print_crlf proc near
  1426.         pushf
  1427.         push    ax
  1428.         push    dx
  1429.         lea     dx,@@crlf
  1430.         call    print
  1431.         pop     dx
  1432.         pop     ax
  1433.         popf
  1434.         ret
  1435. @@crlf  db      13,10,'$'
  1436. print_crlf endp
  1437.  
  1438. print_dot proc  near
  1439.         pushf
  1440.         cmp     cs:print_dots,1
  1441.         jb      @@ex
  1442.         push    ax
  1443.         push    dx
  1444.         lea     dx,@@dot_tx
  1445.         je      @@1
  1446.         lea     dx,@@start_tx
  1447.         dec     cs:print_dots
  1448.         cmp     cs:print_dots,1
  1449.         jbe     @@1
  1450.         lea     dx,@@start_tx_2
  1451.         dec     cs:print_dots
  1452. @@1:
  1453.         call    print
  1454.         pop     dx
  1455.         pop     ax
  1456. @@ex:
  1457.         popf
  1458.         ret
  1459. @@start_tx_2 db  13,10,'Now reading INITRD:'
  1460. @@start_tx db    13,10,'LOADING'
  1461. @@dot_tx  db    '.$'
  1462. print_dot endp
  1463.  
  1464.  
  1465. granularity = 01000h
  1466.  
  1467. read_handle proc    near
  1468. ; input:
  1469. ;   BX=  handle
  1470. ;  ECX=  count
  1471. ;  EDI=  linear destination address
  1472. ; output:
  1473. ;   CARRY =1 , then read-error
  1474. ;  EAX= number of bytes transferred (even on CARRY=1)
  1475. ;
  1476.         push    ds
  1477.         push    esi
  1478.         push    dx
  1479.         push    ecx
  1480.         push    cs
  1481.         pop     ds                 ; target seg = IO_buffer
  1482.         lea     dx,aligned_auxbuff ; target off = IO_buffer
  1483.         mov     esi,ecx
  1484.         mov     ecx,granularity
  1485.         jmp     @@start
  1486. @@next:
  1487.         DosCall DOS_READ_FROM_HANDLE
  1488.         call    print_dot
  1489.         jc      @@err
  1490.         call    put_buffer
  1491.         cmp     ax,cx
  1492.         jne     @@eof
  1493.         sub     esi,ecx
  1494.         add     edi,granularity
  1495. @@start:
  1496.         cmp     esi,ecx
  1497.         ja      @@next
  1498.         mov     cx,si
  1499.         DosCall DOS_READ_FROM_HANDLE
  1500.         call    print_dot
  1501.         jc      @@err
  1502.         call    put_buffer
  1503. @@eof:
  1504.         movzx   eax,ax
  1505.         sub     esi,eax
  1506.         pop     ecx
  1507.         mov     eax,ecx
  1508.         sub     eax,esi
  1509.         clc
  1510. @@ex:
  1511.         pop     dx
  1512.         pop     esi
  1513.         pop     ds
  1514.         ret
  1515. @@err:
  1516.         pop     ecx
  1517.         mov     eax,ecx
  1518.         sub     eax,esi
  1519.         stc
  1520.         jmp     @@ex
  1521. read_handle endp
  1522.  
  1523.  
  1524. clear_to_default proc near
  1525.         push_    ax,di,es
  1526.         call     close_debug_file
  1527.         push     cs
  1528.         pop      es
  1529.         xor      ax,ax
  1530.         mov      cx,parse_switches_end-parse_switches
  1531.         lea      di,parse_switches
  1532.         cld
  1533.         rep stosb
  1534.         pop_     ax,di,es
  1535.         ret
  1536. clear_to_default endp
  1537.  
  1538.  
  1539. ;=============================================================================
  1540.  
  1541. INCLUDE LOADLINI.ASM
  1542. INCLUDE LOADLINJ.ASM
  1543. INCLUDE LOADLINM.ASM
  1544.  
  1545. ;=============================================================================
  1546.  
  1547. ; -------------------------------------------------------------
  1548. clear_uninitialized_data proc near
  1549.         .8086   ; we need to have clean 8086 code,
  1550.                 ; because we don't yet know on which machine we are
  1551.         push_   es,ax,cx,di
  1552.         xor     ax,ax
  1553.         lea     di,uninitialized_data_start
  1554.         mov     cx,(uninitialized_data_stop-uninitialized_data_start)/2
  1555.         cld
  1556.         rep stosw
  1557.         call    preset_pagedir_from_template
  1558.         les     ax,@@aux
  1559.         mov     word ptr pageadjlist.auxbuf,ax
  1560.         mov     word ptr pageadjlist.auxbuf+2,es
  1561.         pop_    es,ax,cx,di
  1562.         ret
  1563.         .386
  1564. @@aux    dd     ((High_Seg_*16) + (aligned_auxbuff-code_org0))
  1565. clear_uninitialized_data endp
  1566.  
  1567. preset_pagedir_from_template proc near
  1568.         mov     ax,word ptr pagedir_template
  1569.         mov     word ptr pagedir,ax
  1570.         mov     ax,word ptr pagedir_template+2
  1571.         mov     word ptr pagedir+2,ax
  1572.         ret
  1573. preset_pagedir_from_template endp
  1574.  
  1575. ;------------------------------------------------------------------------
  1576. ; Here we expect the realy end of any _preset_ data in the .EXE.
  1577. ; Below we have _uninitialized_ data, that will not appear in the binary.
  1578. ; We put the LOADLIN >= 1.6 Magic and suffix-structure here:
  1579.           align  dword
  1580.           dd     0     ; relative offset within file to previous suffix
  1581.                        ; (e.g the size of the appended part)
  1582.           dd     0     ; flags, indicating what kind of appended
  1583.                        ; file we have
  1584.           db     0     ; suffix level, 0= no further suffix
  1585.           db     'Loadlin-',LOADLIN_VERSION ; exactly 11 bytes !!!
  1586. ;------------------------------------------------------------------------
  1587.  
  1588.  
  1589. ;          align dword       ; NOTE: this is align from above !
  1590.                              ; if we realign it here, we may get the
  1591.                              ; suffix above corrupted, because it then isn't
  1592.                              ; the last part of the executable (.EXE)
  1593.           db           space1k dup(?)
  1594. setup_stack_top label byte
  1595.           db           space1k dup(?)
  1596. stack_top label byte
  1597.  
  1598.  
  1599. uninitialized_data_start label byte
  1600.  
  1601.                 db    ?   ; belongs to comline
  1602. comline         db    128 dup(?) ; copied from PSP_DTA
  1603.                 db    2*1024-128 dup(?) ; extended commandline
  1604. comline_end     label byte
  1605. image_name      db    80 dup(?)
  1606. aux_token       db    80 dup(?)
  1607. rdimage_name    db    80 dup(?)
  1608. command_line    db    space2k dup(?)  ; kernel accepts maximum of 2Kb
  1609.  
  1610.  
  1611.   ; -------------------------------v
  1612.                              ; this is for 32-bit code
  1613. pageadjlist     pages_list   <?>
  1614.   ; -------------------------------^
  1615.  
  1616.   ; -------------------------------v
  1617.   ; this buffer is for the "default bios interruptvectors"
  1618.   ; as is set from the BIOS,
  1619.   ; Its contents are delivered by the BIOSINTV.SYS device driver
  1620.   ; (must be AT TOP of config.sys).
  1621.   ; Or from the REALBIOS.INT file.
  1622.   ; We need this after returning from V86-mode
  1623.   ; because NOTHING is valid any more but the ROM-BIOS
  1624.   ; (and LOADLIN of cause)
  1625.   ;
  1626. intv_buf        dd     128 dup(?)   ;  intvector  0:0
  1627.                 dd     128 dup(?)
  1628. bios_data       db     256 dup(?)   ;  BIOS-data 40:0
  1629. dummy_dos_data  db     (256-4-16-2) dup(?) ; (DOS-data  50:0, not valid at boot tome
  1630. real_bios_int15 dw     ?            ; result of int15 at time of realbios
  1631. real_bios_magic dw     ?            ; must be 0a5a5h for post alpha-release
  1632. reset_jmpop     db     ?            ;  TOP BIOS FFFF:0
  1633. reset_entry     dd     ?
  1634. biosdate        db     9 dup(?)
  1635. machineid       db     ?
  1636.                 db     ?
  1637. masterIMR       db     ?            ;  port 21
  1638. slaveIMR        db     ?            ;  port A1
  1639. bios_scratch    db     1024 dup(?)  ;  scratch  9FC0:0
  1640. realbios_end    label  byte
  1641.   ; -------------------------------^
  1642.  
  1643.   ; -------------------------------v
  1644.                 align_ code_org0,4096
  1645. aligned_auxbuff dd     1024 dup(?)  ; must be aligned to 4 K
  1646. page0           dd     1024 dup(?)  ; must be aligned to 4 K
  1647.   ; -------------------------------^
  1648.  
  1649.  
  1650. uninitialized_data_stop label byte
  1651. ; -------------------------------------------------------------
  1652.  
  1653.  
  1654. modul_end:
  1655.  
  1656. code    ends
  1657.  
  1658.         end      start
  1659.