/* * * bootsect.s (C) 1991 Linus Torvalds * * bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves * iself out of the way to address 0x90000, and jumps there. * * It then loads 'setup' directly after itself (0x90200), and the system * at 0x10000, using BIOS interrupts. * * NOTE! currently system is at most 8*65536 bytes long. This should be no * problem, even in the future. I want to keep it simple. This 512 kB * kernel size should be enough, especially as this doesn't contain the * buffer cache as in minix * * The loader has been made as simple as possible, and continuos * read errors will result in a unbreakable loop. Reboot by hand. It * loads pretty fast by getting whole sectors at a time whenever possible. */ .globl begtext, begdata, begbss, endtext, enddata, endbss .text begtext: .data begdata: .bss begbss: .text SETUPLEN = 4 # nr of setup-sectors BOOTSEG = 0x07c0 # original address of boot-sector INITSEG = 0x9000 # we move boot here - out of the way SETUPSEG = 0x9020 # setup starts here SYSSEG = 0x1000 # system loaded at 0x10000 (65536). ENDSEG = SYSSEG + SYSSIZE # where to stop loading /* * ROOT_DEV: 0x000 - same type of floppy as boot. * 0x301 - first partition on first drive etc */ ROOT_DEV = 0 # 0x306 entry start start: mov $BOOTSEG,%ax mov %ax,%ds mov $INITSEG,%ax mov %ax,%es mov $256,%cx sub %si,%si sub %di,%di rep movw jmpi go,INITSEG go: mov %cs,%ax mov %ax,%ds mov %ax,%es /* * put stack at 0x9ff00. */ mov %ax,%ss mov $0xFF00,%sp # arbitrary value >>512 /* * load the setup-sectors directly after the bootblock. * Note that 'es' is already set up. */ load_setup: mov $0x0000,%dx # drive 0, head 0 mov $0x0002,%cx # sector 2, track 0 mov $0x0200,%bx # address = 512, in INITSEG mov $0x0200,%ax+SETUPLEN # service 2, nr of sectors int 0x13 # read it jnc ok_load_setup # ok - continue mov $0x0000,%dx mov $0x0000,%ax # reset the diskette int 0x13 j load_setup ok_load_setup: /* * Get disk drive parameters, specifically nr of sectors/track */ mov $0x00,%dl mov $0x0800,%ax # AH=8 is get drive parameters int 0x13 mov $0x00,%ch seg %cs mov %cx,sectors mov $INITSEG,%ax mov %ax,%es /* * Print some inane message */ mov $0x03,%ah # read cursor pos xor %bh,%bh int 0x10 mov $24,%cx mov $0x0007,%bx # page 0, attribute 7 (normal) mov $msg1,%bp mov $0x1301,%ax # write string, move cursor int 0x10 /* * ok, we've written the message, now * we want to load the system (at 0x10000) */ mov $SYSSEG,%ax mov %ax,%es # segment of 0x010000 call read_it call kill_motor /* * After that we check which root-device to use. If the device is * defined (!= 0), nothing is done and the given device is used. * Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending * on the number of sectors that the BIOS reports currently. */ seg %cs mov root,%ax_dev cmp %ax,$0 jne root_defined seg %cs mov sectors,%bx mov $0x0208,%ax # /dev/ps0 - 1.2Mb cmp %bx,$15 je root_defined mov $0x021c,%ax # /dev/PS0 - 1.44Mb cmp %bx,$18 je root_defined undef_root: jmp undef_root root_defined: seg %cs mov root_%ax,dev /* * after that (everyting loaded), we jump to * the setup-routine loaded directly after * the bootblock: */ jmpi 0,SETUPSEG /* * This routine loads the system at address 0x10000, making sure * no 64kB boundaries are crossed. We try to load it as fast as * possible, loading whole tracks whenever we can. * * in: es - starting address segment (normally 0x1000) * */ sread: .word 1+SETUPLEN # sectors read of current track head: .word 0 # current head track: .word 0 # current track read_it: mov %es,%ax test %ax,$0x0fff die: jne die # %es must be at 64kB boundary xor %bx,%bx # %bx is starting address within segment rp_read: mov %es,%ax cmp %ax,$ENDSEG # have we loaded all yet? jb ok1_read ret ok1_read: seg %cs mov sectors,%ax sub sread,%ax mov %ax,%cx shl $9,%cx add %bx,%cx jnc ok2_read je ok2_read xor %ax,%ax sub %bx,%ax shr $9,%ax ok2_read: call read_track mov %ax,%cx add sread,%ax seg %cs cmp %ax,sectors jne ok3_read mov $1,%ax sub head,%ax jne ok4_read inc track ok4_read: mov %ax,head xor %ax,%ax ok3_read: mov %ax,sread shl $9,%cx add %cx,%bx jnc rp_read mov %es,%ax add $0x1000,%ax mov %ax,%es xor %bx,%bx jmp rp_read read_track: push %ax push %bx push %cx push %dx mov track,%dx mov sread,%cx inc %cx mov %dl,%ch mov head,%dx mov %dl,%dh mov $0,%dl and $0x0100,%dx mov $2,%ah int 0x13 jc bad_rt pop %dx pop %cx pop %bx pop %ax ret bad_rt: mov %ax,$0 mov $0,%dx int 0x13 pop %dx pop %cx pop %bx pop %ax jmp read_track /* * This procedure turns off the floppy drive motor, so * that we enter the kernel in a known state, and * don't have to worry about it later. */ kill_motor: push %dx mov $0x3f2,%dx mov $0,%al outb pop %dx ret sectors: .word 0 msg1: .byte 13,10 .ascii "Loading system ..." .byte 13,10,13,10 .org 508 root_dev: .word ROOT_DEV boot_flag: .word 0xAA55 .text endtext: .data enddata: .bss endbss: