home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / boot / bootsect.S next >
Encoding:
Text File  |  1993-12-01  |  9.0 KB  |  451 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 continuos
  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. go:    mov    ax,cs        
  72.     mov    dx,#0x4000-12    ! 0x4000 is arbitrary value >= length of
  73.                 ! bootsect + length of setup + room for stack
  74.                 ! 12 is disk parm size
  75.  
  76. ! bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde).  We
  77. ! wouldn't have to worry about this if we checked the top of memory.  Also
  78. ! my BIOS can be configured to put the wini drive tables in high memory
  79. ! instead of in the vector table.  The old stack might have clobbered the
  80. ! drive table.
  81.  
  82.     mov    ds,ax
  83.     mov    es,ax
  84.     mov    ss,ax        ! put stack at INITSEG:0x4000-12.
  85.     mov    sp,dx
  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 18 - the most we will encounter on an HD 1.44.  
  96.  *
  97.  *    High doesn't hurt.  Low does.
  98.  *
  99.  *    Segments are as follows: ds=es=ss=cs - INITSEG,
  100.  *        fs = 0, gs = parameter table segment
  101.  */
  102.  
  103.     push    #0
  104.     pop    fs
  105.     mov    bx,#0x78        ! fs:bx is parameter table address
  106.     seg fs
  107.     lgs    si,(bx)            ! gs:si is source
  108.  
  109.     mov    di,dx            ! es:di is destination
  110.     mov    cx,#6            ! copy 12 bytes
  111.     cld
  112.  
  113.     rep
  114.     seg gs
  115.     movsw
  116.  
  117.     mov    di,dx
  118.     movb    4(di),*18        ! patch sector count
  119.  
  120.     seg fs
  121.     mov    (bx),di
  122.     seg fs
  123.     mov    2(bx),es
  124.  
  125.     mov    ax,cs
  126.     mov    fs,ax
  127.     mov    gs,ax
  128.     
  129.     xor    ah,ah            ! reset FDC 
  130.     xor    dl,dl
  131.     int     0x13    
  132.  
  133. ! load the setup-sectors directly after the bootblock.
  134. ! Note that 'es' is already set up.
  135.  
  136. load_setup:
  137.     xor    dx, dx            ! drive 0, head 0
  138.     mov    cx,#0x0002        ! sector 2, track 0
  139.     mov    bx,#0x0200        ! address = 512, in INITSEG
  140.     mov    ax,#0x0200+SETUPSECS    ! service 2, nr of sectors
  141.                     ! (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.     xor    dl, dl            ! reset FDC
  152.     xor    ah, ah
  153.     int    0x13
  154.     jmp    load_setup
  155.  
  156. ok_load_setup:
  157.  
  158. ! Get disk drive parameters, specifically nr of sectors/track
  159.  
  160. #if 0
  161.  
  162. ! bde - the Phoenix BIOS manual says function 0x08 only works for fixed
  163. ! disks.  It doesn't work for one of my BIOS's (1987 Award).  It was
  164. ! fatal not to check the error code.
  165.  
  166.     xor    dl,dl
  167.     mov    ah,#0x08        ! AH=8 is get drive parameters
  168.     int    0x13
  169.     xor    ch,ch
  170. #else
  171.  
  172. ! It seems that there is no BIOS call to get the number of sectors.  Guess
  173. ! 18 sectors if sector 18 can be read, 15 if sector 15 can be read.
  174. ! Otherwise guess 9.
  175.  
  176.     xor    dx, dx            ! drive 0, head 0
  177.     mov    cx,#0x0012        ! sector 18, track 0
  178.     mov    bx,#0x0200+SETUPSECS*0x200  ! address after setup (es = cs)
  179.     mov    ax,#0x0201        ! service 2, 1 sector
  180.     int    0x13
  181.     jnc    got_sectors
  182.     mov    cl,#0x0f        ! sector 15
  183.     mov    ax,#0x0201        ! service 2, 1 sector
  184.     int    0x13
  185.     jnc    got_sectors
  186.     mov    cl,#0x09
  187.  
  188. #endif
  189.  
  190. got_sectors:
  191.     seg cs
  192.     mov    sectors,cx
  193.     mov    ax,#INITSEG
  194.     mov    es,ax
  195.  
  196. ! Print some inane message
  197.  
  198.     mov    ah,#0x03        ! read cursor pos
  199.     xor    bh,bh
  200.     int    0x10
  201.     
  202.     mov    cx,#9
  203.     mov    bx,#0x0007        ! page 0, attribute 7 (normal)
  204.     mov    bp,#msg1
  205.     mov    ax,#0x1301        ! write string, move cursor
  206.     int    0x10
  207.  
  208. ! ok, we've written the message, now
  209. ! we want to load the system (at 0x10000)
  210.  
  211.     mov    ax,#SYSSEG
  212.     mov    es,ax        ! segment of 0x010000
  213.     call    read_it
  214.     call    kill_motor
  215.     call    print_nl
  216.  
  217. ! After that we check which root-device to use. If the device is
  218. ! defined (!= 0), nothing is done and the given device is used.
  219. ! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
  220. ! on the number of sectors that the BIOS reports currently.
  221.  
  222.     seg cs
  223.     mov    ax,root_dev
  224.     or    ax,ax
  225.     jne    root_defined
  226.     seg cs
  227.     mov    bx,sectors
  228.     mov    ax,#0x0208        ! /dev/ps0 - 1.2Mb
  229.     cmp    bx,#15
  230.     je    root_defined
  231.     mov    ax,#0x021c        ! /dev/PS0 - 1.44Mb
  232.     cmp    bx,#18
  233.     je    root_defined
  234.     mov    ax,#0x0200        ! /dev/fd0 - autodetect
  235. root_defined:
  236.     seg cs
  237.     mov    root_dev,ax
  238.  
  239. ! after that (everyting loaded), we jump to
  240. ! the setup-routine loaded directly after
  241. ! the bootblock:
  242.  
  243.     jmpi    0,SETUPSEG
  244.  
  245. ! This routine loads the system at address 0x10000, making sure
  246. ! no 64kB boundaries are crossed. We try to load it as fast as
  247. ! possible, loading whole tracks whenever we can.
  248. !
  249. ! in:    es - starting address segment (normally 0x1000)
  250. !
  251. sread:    .word 1+SETUPSECS    ! sectors read of current track
  252. head:    .word 0            ! current head
  253. track:    .word 0            ! current track
  254.  
  255. read_it:
  256.     mov ax,es
  257.     test ax,#0x0fff
  258. die:    jne die            ! es must be at 64kB boundary
  259.     xor bx,bx        ! bx is starting address within segment
  260. rp_read:
  261.     mov ax,es
  262.     sub ax,#SYSSEG
  263.     cmp ax,syssize        ! have we loaded all yet?
  264.     jbe ok1_read
  265.     ret
  266. ok1_read:
  267.     seg cs
  268.     mov ax,sectors
  269.     sub ax,sread
  270.     mov cx,ax
  271.     shl cx,#9
  272.     add cx,bx
  273.     jnc ok2_read
  274.     je ok2_read
  275.     xor ax,ax
  276.     sub ax,bx
  277.     shr ax,#9
  278. ok2_read:
  279.     call read_track
  280.     mov cx,ax
  281.     add ax,sread
  282.     seg cs
  283.     cmp ax,sectors
  284.     jne ok3_read
  285.     mov ax,#1
  286.     sub ax,head
  287.     jne ok4_read
  288.     inc track
  289. ok4_read:
  290.     mov head,ax
  291.     xor ax,ax
  292. ok3_read:
  293.     mov sread,ax
  294.     shl cx,#9
  295.     add bx,cx
  296.     jnc rp_read
  297.     mov ax,es
  298.     add ah,#0x10
  299.     mov es,ax
  300.     xor bx,bx
  301.     jmp rp_read
  302.  
  303. read_track:
  304.     pusha
  305.     pusha    
  306.     mov    ax, #0xe2e     ! loading... message 2e = .
  307.     mov    bx, #7
  308.      int    0x10
  309.     popa        
  310.  
  311.     mov    dx,track
  312.     mov    cx,sread
  313.     inc    cx
  314.     mov    ch,dl
  315.     mov    dx,head
  316.     mov    dh,dl
  317.     and    dx,#0x0100
  318.     mov    ah,#2
  319.     
  320.     push    dx                ! save for error dump
  321.     push    cx
  322.     push    bx
  323.     push    ax
  324.  
  325.     int    0x13
  326.     jc    bad_rt
  327.     add    sp, #8
  328.     popa
  329.     ret
  330.  
  331. bad_rt:    push    ax                ! save error code
  332.     call    print_all            ! ah = error, al = read
  333.     
  334.     
  335.     xor ah,ah
  336.     xor dl,dl
  337.     int 0x13
  338.     
  339.  
  340.     add    sp, #10
  341.     popa    
  342.     jmp read_track
  343.  
  344. /*
  345.  *    print_all is for debugging purposes.  
  346.  *    It will print out all of the registers.  The assumption is that this is
  347.  *    called from a routine, with a stack frame like
  348.  *    dx 
  349.  *    cx
  350.  *    bx
  351.  *    ax
  352.  *    error
  353.  *    ret <- sp
  354.  *
  355. */
  356.  
  357. print_all:
  358.     mov    cx, #5        ! error code + 4 registers
  359.     mov    bp, sp    
  360.  
  361. print_loop:
  362.     push    cx        ! save count left
  363.     call    print_nl    ! nl for readability
  364.  
  365.     cmp    cl, 5
  366.     jae    no_reg        ! see if register name is needed
  367.     
  368.     mov    ax, #0xe05 + 'A - 1
  369.     sub    al, cl
  370.     int    0x10
  371.  
  372.     mov    al, #'X
  373.     int    0x10
  374.  
  375.     mov    al, #':
  376.     int    0x10
  377.  
  378. no_reg:
  379.     add    bp, #2        ! next register
  380.     call    print_hex    ! print it
  381.     pop    cx
  382.     loop    print_loop
  383.     ret
  384.  
  385. print_nl:
  386.     mov    ax, #0xe0d    ! CR
  387.     int    0x10
  388.     mov    al, #0xa    ! LF
  389.     int     0x10
  390.     ret
  391.  
  392. /*
  393.  *    print_hex is for debugging purposes, and prints the word
  394.  *    pointed to by ss:bp in hexadecmial.
  395. */
  396.  
  397. print_hex:
  398.     mov    cx, #4        ! 4 hex digits
  399.     mov    dx, (bp)    ! load word into dx
  400. print_digit:
  401.     rol    dx, #4        ! rotate so that lowest 4 bits are used
  402.     mov    ah, #0xe    
  403.     mov    al, dl        ! mask off so we have only next nibble
  404.     and    al, #0xf
  405.     add    al, #'0        ! convert to 0-based digit
  406.     cmp    al, #'9        ! check for overflow
  407.     jbe    good_digit
  408.     add    al, #'A - '0 - 10
  409.  
  410. good_digit:
  411.     int    0x10
  412.     loop    print_digit
  413.     ret
  414.  
  415.  
  416. /*
  417.  * This procedure turns off the floppy drive motor, so
  418.  * that we enter the kernel in a known state, and
  419.  * don't have to worry about it later.
  420.  */
  421. kill_motor:
  422.     push dx
  423.     mov dx,#0x3f2
  424.     xor al, al
  425.     outb
  426.     pop dx
  427.     ret
  428.  
  429. sectors:
  430.     .word 0
  431.  
  432. msg1:
  433.     .byte 13,10
  434.     .ascii "Loading"
  435.  
  436. .org 498
  437. root_flags:
  438.     .word CONFIG_ROOT_RDONLY
  439. syssize:
  440.     .word SYSSIZE
  441. swap_dev:
  442.     .word SWAP_DEV
  443. ram_size:
  444.     .word RAMDISK
  445. vid_mode:
  446.     .word SVGA_MODE
  447. root_dev:
  448.     .word ROOT_DEV
  449. boot_flag:
  450.     .word 0xAA55
  451.