home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / arch / i386 / boot / bootsect.S next >
Encoding:
Text File  |  1994-08-10  |  9.2 KB  |  461 lines

  1. !
  2. ! SYS_SIZE is the number of clicks (16 bytes) to be loaded.
  3. ! 0x7F00 is 0x7F000 bytes = 508kB, more than enough for current
  4. ! versions of linux which compress the kernel
  5. !
  6. #include <linux/config.h>
  7. SYSSIZE = DEF_SYSSIZE
  8. !
  9. !    bootsect.s        Copyright (C) 1991, 1992 Linus Torvalds
  10. !    modified by Drew Eckhardt
  11. !    modified by Bruce Evans (bde)
  12. !
  13. ! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
  14. ! itself out of the way to address 0x90000, and jumps there.
  15. !
  16. ! bde - should not jump blindly, there may be systems with only 512K low
  17. ! memory.  Use int 0x12 to get the top of memory, etc.
  18. !
  19. ! It then loads 'setup' directly after itself (0x90200), and the system
  20. ! at 0x10000, using BIOS interrupts. 
  21. !
  22. ! NOTE! currently system is at most (8*65536-4096) bytes long. This should 
  23. ! be no problem, even in the future. I want to keep it simple. This 508 kB
  24. ! kernel size should be enough, especially as this doesn't contain the
  25. ! buffer cache as in minix (and especially now that the kernel is 
  26. ! compressed :-)
  27. !
  28. ! The loader has been made as simple as possible, and continuous
  29. ! read errors will result in a unbreakable loop. Reboot by hand. It
  30. ! loads pretty fast by getting whole tracks at a time whenever possible.
  31.  
  32. .text
  33.  
  34. SETUPSECS = 4                ! nr of setup-sectors
  35. BOOTSEG   = 0x07C0            ! original address of boot-sector
  36. INITSEG   = DEF_INITSEG            ! we move boot here - out of the way
  37. SETUPSEG  = DEF_SETUPSEG        ! setup starts here
  38. SYSSEG    = DEF_SYSSEG            ! system loaded at 0x10000 (65536).
  39.  
  40. ! ROOT_DEV & SWAP_DEV are now written by "build".
  41. ROOT_DEV = 0
  42. SWAP_DEV = 0
  43. #ifndef SVGA_MODE
  44. #define SVGA_MODE ASK_VGA
  45. #endif
  46. #ifndef RAMDISK
  47. #define RAMDISK 0
  48. #endif 
  49. #ifndef CONFIG_ROOT_RDONLY
  50. #define CONFIG_ROOT_RDONLY 0
  51. #endif
  52.  
  53. ! ld86 requires an entry symbol. This may as well be the usual one.
  54. .globl    _main
  55. _main:
  56. #if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */
  57.     int    3
  58. #endif
  59.     mov    ax,#BOOTSEG
  60.     mov    ds,ax
  61.     mov    ax,#INITSEG
  62.     mov    es,ax
  63.     mov    cx,#256
  64.     sub    si,si
  65.     sub    di,di
  66.     cld
  67.     rep
  68.     movsw
  69.     jmpi    go,INITSEG
  70.  
  71. ! ax and es already contain INITSEG
  72.  
  73. go:    mov    di,#0x4000-12    ! 0x4000 is arbitrary value >= length of
  74.                 ! bootsect + length of setup + room for stack
  75.                 ! 12 is disk parm size
  76.  
  77. ! bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde).  We
  78. ! wouldn't have to worry about this if we checked the top of memory.  Also
  79. ! my BIOS can be configured to put the wini drive tables in high memory
  80. ! instead of in the vector table.  The old stack might have clobbered the
  81. ! drive table.
  82.  
  83.     mov    ds,ax
  84.     mov    ss,ax        ! put stack at INITSEG:0x4000-12.
  85.     mov    sp,di
  86. /*
  87.  *    Many BIOS's default disk parameter tables will not 
  88.  *    recognize multi-sector reads beyond the maximum sector number
  89.  *    specified in the default diskette parameter tables - this may
  90.  *    mean 7 sectors in some cases.
  91.  *
  92.  *    Since single sector reads are slow and out of the question,
  93.  *    we must take care of this by creating new parameter tables
  94.  *    (for the first disk) in RAM.  We will set the maximum sector
  95.  *    count to 36 - the most we will encounter on an ED 2.88.  
  96.  *
  97.  *    High doesn't hurt.  Low does.
  98.  *
  99.  *    Segments are as follows: ds=es=ss=cs - INITSEG,
  100.  *        fs = 0, gs is unused.
  101.  */
  102.  
  103. ! cx contains 0 from rep movsw above
  104.  
  105.     mov    fs,cx
  106.     mov    bx,#0x78        ! fs:bx is parameter table address
  107.     push    ds
  108.     seg fs
  109.     lds    si,(bx)            ! ds:si is source
  110.  
  111.     mov    cl,#6            ! copy 12 bytes
  112.     cld
  113.     push    di
  114.  
  115.     rep
  116.     movsw
  117.  
  118.     pop    di
  119.     pop    ds
  120.  
  121.     movb    4(di),*36        ! patch sector count
  122.  
  123.     seg fs
  124.     mov    (bx),di
  125.     seg fs
  126.     mov    2(bx),es
  127.  
  128. ! load the setup-sectors directly after the bootblock.
  129. ! Note that 'es' is already set up.
  130. ! Also cx is 0 from rep movsw above.
  131.  
  132. load_setup:
  133.     xor    ah,ah            ! reset FDC 
  134.     xor    dl,dl
  135.     int     0x13    
  136.  
  137.     xor    dx, dx            ! drive 0, head 0
  138.     mov    cl,#0x02        ! sector 2, track 0
  139.     mov    bx,#0x0200        ! address = 512, in INITSEG
  140.     mov    ah,#0x02        ! service 2, nr of sectors
  141.     mov    al,setup_sects        ! (assume all on head 0, track 0)
  142.     int    0x13            ! read it
  143.     jnc    ok_load_setup        ! ok - continue
  144.  
  145.     push    ax            ! dump error code
  146.     call    print_nl
  147.     mov    bp, sp
  148.     call    print_hex
  149.     pop    ax    
  150.     
  151.     jmp    load_setup
  152.  
  153. ok_load_setup:
  154.  
  155. ! Get disk drive parameters, specifically nr of sectors/track
  156.  
  157. #if 0
  158.  
  159. ! bde - the Phoenix BIOS manual says function 0x08 only works for fixed
  160. ! disks.  It doesn't work for one of my BIOS's (1987 Award).  It was
  161. ! fatal not to check the error code.
  162.  
  163.     xor    dl,dl
  164.     mov    ah,#0x08        ! AH=8 is get drive parameters
  165.     int    0x13
  166.     xor    ch,ch
  167. #else
  168.  
  169. ! It seems that there is no BIOS call to get the number of sectors.  Guess
  170. ! 36 sectors if sector 36 can be read, 18 sectors if sector 18 can be read,
  171. ! 15 if sector 15 can be read.  Otherwise guess 9.
  172.  
  173.     mov    si,#disksizes        ! table of sizes to try
  174.  
  175. probe_loop:
  176.     lodsb
  177.     cbw                ! extend to word
  178.     mov    sectors, ax
  179.     cmp    si,#disksizes+4
  180.     jae    got_sectors        ! if all else fails, try 9
  181.     xchg    ax, cx            ! cx = track and sector
  182.     xor    dx, dx            ! drive 0, head 0
  183.     xor    bl, bl
  184.     mov    bh,setup_sects
  185.     inc    bh
  186.     shl    bh,#1            ! address after setup (es = cs)
  187.     mov    ax,#0x0201        ! service 2, 1 sector
  188.     int    0x13
  189.     jc    probe_loop        ! try next value
  190.  
  191. #endif
  192.  
  193. got_sectors:
  194.  
  195. ! Restore es
  196.  
  197.     mov    ax,#INITSEG
  198.     mov    es,ax
  199.  
  200. ! Print some inane message
  201.  
  202.     mov    ah,#0x03        ! read cursor pos
  203.     xor    bh,bh
  204.     int    0x10
  205.     
  206.     mov    cx,#9
  207.     mov    bx,#0x0007        ! page 0, attribute 7 (normal)
  208.     mov    bp,#msg1
  209.     mov    ax,#0x1301        ! write string, move cursor
  210.     int    0x10
  211.  
  212. ! ok, we've written the message, now
  213. ! we want to load the system (at 0x10000)
  214.  
  215.     mov    ax,#SYSSEG
  216.     mov    es,ax        ! segment of 0x010000
  217.     call    read_it
  218.     call    kill_motor
  219.     call    print_nl
  220.  
  221. ! After that we check which root-device to use. If the device is
  222. ! defined (!= 0), nothing is done and the given device is used.
  223. ! Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8),
  224. ! depending on the number of sectors we pretend to know we have.
  225.  
  226.     seg cs
  227.     mov    ax,root_dev
  228.     or    ax,ax
  229.     jne    root_defined
  230.     seg cs
  231.     mov    bx,sectors
  232.     mov    ax,#0x0208        ! /dev/ps0 - 1.2Mb
  233.     cmp    bx,#15
  234.     je    root_defined
  235.     mov    al,#0x1c        ! /dev/PS0 - 1.44Mb
  236.     cmp    bx,#18
  237.     je    root_defined
  238.     mov    al,#0x20        ! /dev/fd0H2880 - 2.88Mb
  239.     cmp    bx,#36
  240.     je    root_defined
  241.     mov    al,#0            ! /dev/fd0 - autodetect
  242. root_defined:
  243.     seg cs
  244.     mov    root_dev,ax
  245.  
  246. ! after that (everything loaded), we jump to
  247. ! the setup-routine loaded directly after
  248. ! the bootblock:
  249.  
  250.     jmpi    0,SETUPSEG
  251.  
  252. ! This routine loads the system at address 0x10000, making sure
  253. ! no 64kB boundaries are crossed. We try to load it as fast as
  254. ! possible, loading whole tracks whenever we can.
  255. !
  256. ! in:    es - starting address segment (normally 0x1000)
  257. !
  258. sread:    .word 0            ! sectors read of current track
  259. head:    .word 0            ! current head
  260. track:    .word 0            ! current track
  261.  
  262. read_it:
  263.     mov    al,setup_sects
  264.     inc    al
  265.     mov    sread,al
  266.     mov ax,es
  267.     test ax,#0x0fff
  268. die:    jne die            ! es must be at 64kB boundary
  269.     xor bx,bx        ! bx is starting address within segment
  270. rp_read:
  271.     mov ax,es
  272.     sub ax,#SYSSEG
  273.     cmp ax,syssize        ! have we loaded all yet?
  274.     jbe ok1_read
  275.     ret
  276. ok1_read:
  277.     mov ax,sectors
  278.     sub ax,sread
  279.     mov cx,ax
  280.     shl cx,#9
  281.     add cx,bx
  282.     jnc ok2_read
  283.     je ok2_read
  284.     xor ax,ax
  285.     sub ax,bx
  286.     shr ax,#9
  287. ok2_read:
  288.     call read_track
  289.     mov cx,ax
  290.     add ax,sread
  291.     cmp ax,sectors
  292.     jne ok3_read
  293.     mov ax,#1
  294.     sub ax,head
  295.     jne ok4_read
  296.     inc track
  297. ok4_read:
  298.     mov head,ax
  299.     xor ax,ax
  300. ok3_read:
  301.     mov sread,ax
  302.     shl cx,#9
  303.     add bx,cx
  304.     jnc rp_read
  305.     mov ax,es
  306.     add ah,#0x10
  307.     mov es,ax
  308.     xor bx,bx
  309.     jmp rp_read
  310.  
  311. read_track:
  312.     pusha
  313.     pusha    
  314.     mov    ax, #0xe2e     ! loading... message 2e = .
  315.     mov    bx, #7
  316.      int    0x10
  317.     popa        
  318.  
  319.     mov    dx,track
  320.     mov    cx,sread
  321.     inc    cx
  322.     mov    ch,dl
  323.     mov    dx,head
  324.     mov    dh,dl
  325.     and    dx,#0x0100
  326.     mov    ah,#2
  327.     
  328.     push    dx                ! save for error dump
  329.     push    cx
  330.     push    bx
  331.     push    ax
  332.  
  333.     int    0x13
  334.     jc    bad_rt
  335.     add    sp, #8
  336.     popa
  337.     ret
  338.  
  339. bad_rt:    push    ax                ! save error code
  340.     call    print_all            ! ah = error, al = read
  341.     
  342.     
  343.     xor ah,ah
  344.     xor dl,dl
  345.     int 0x13
  346.     
  347.  
  348.     add    sp, #10
  349.     popa    
  350.     jmp read_track
  351.  
  352. /*
  353.  *    print_all is for debugging purposes.  
  354.  *    It will print out all of the registers.  The assumption is that this is
  355.  *    called from a routine, with a stack frame like
  356.  *    dx 
  357.  *    cx
  358.  *    bx
  359.  *    ax
  360.  *    error
  361.  *    ret <- sp
  362.  *
  363. */
  364.  
  365. print_all:
  366.     mov    cx, #5        ! error code + 4 registers
  367.     mov    bp, sp    
  368.  
  369. print_loop:
  370.     push    cx        ! save count left
  371.     call    print_nl    ! nl for readability
  372.  
  373.     cmp    cl, #5
  374.     jae    no_reg        ! see if register name is needed
  375.     
  376.     mov    ax, #0xe05 + 'A - 1
  377.     sub    al, cl
  378.     int    0x10
  379.  
  380.     mov    al, #'X
  381.     int    0x10
  382.  
  383.     mov    al, #':
  384.     int    0x10
  385.  
  386. no_reg:
  387.     add    bp, #2        ! next register
  388.     call    print_hex    ! print it
  389.     pop    cx
  390.     loop    print_loop
  391.     ret
  392.  
  393. print_nl:
  394.     mov    ax, #0xe0d    ! CR
  395.     int    0x10
  396.     mov    al, #0xa    ! LF
  397.     int     0x10
  398.     ret
  399.  
  400. /*
  401.  *    print_hex is for debugging purposes, and prints the word
  402.  *    pointed to by ss:bp in hexadecimal.
  403. */
  404.  
  405. print_hex:
  406.     mov    cx, #4        ! 4 hex digits
  407.     mov    dx, (bp)    ! load word into dx
  408. print_digit:
  409.     rol    dx, #4        ! rotate so that lowest 4 bits are used
  410.     mov    ax, #0xe0f    ! ah = request, al = mask for nybble
  411.     and    al, dl
  412.     add    al, #0x90    ! convert al to ascii hex (four instructions)
  413.     daa
  414.     adc    al, #0x40
  415.     daa
  416.     int    0x10
  417.     loop    print_digit
  418.     ret
  419.  
  420.  
  421. /*
  422.  * This procedure turns off the floppy drive motor, so
  423.  * that we enter the kernel in a known state, and
  424.  * don't have to worry about it later.
  425.  */
  426. kill_motor:
  427.     push dx
  428.     mov dx,#0x3f2
  429.     xor al, al
  430.     outb
  431.     pop dx
  432.     ret
  433.  
  434. sectors:
  435.     .word 0
  436.  
  437. disksizes:
  438.     .byte 36,18,15,9
  439.  
  440. msg1:
  441.     .byte 13,10
  442.     .ascii "Loading"
  443.  
  444. .org 497
  445. setup_sects:
  446.     .byte SETUPSECS
  447. root_flags:
  448.     .word CONFIG_ROOT_RDONLY
  449. syssize:
  450.     .word SYSSIZE
  451. swap_dev:
  452.     .word SWAP_DEV
  453. ram_size:
  454.     .word RAMDISK
  455. vid_mode:
  456.     .word SVGA_MODE
  457. root_dev:
  458.     .word ROOT_DEV
  459. boot_flag:
  460.     .word 0xAA55
  461.