?? boothead.s
字號:
! Boothead.s - BIOS support for boot.c Author: Kees J. Bot!!! This file contains the startup and low level support for the secondary! boot program. It contains functions for disk, tty and keyboard I/O,! copying memory to arbitrary locations, etc.!! The primary bootstrap code supplies the following parameters in registers:! dl = Boot-device.! es:si = Partition table entry if hard disk.!.define begtext, begdata, begbss.databegdata: .ascii "(null)\0".bssbegbss: BOOTOFF = 0x7C00 ! 0x0000:BOOTOFF load a bootstrap here LOADSEG = 0x1000 ! Where this code is loaded. BUFFER = 0x0600 ! First free memory PENTRYSIZE = 16 ! Partition table entry size. DSKBASE = 120 ! 120 = 4 * 0x1E = ptr to disk parameters DSKPARSIZE = 11 ! 11 bytes of floppy parameters SECTORS = 4 ! Offset into parameters to sectors per track a_flags = 2 ! From a.out.h, struct exec a_text = 8 a_data = 12 a_bss = 16 a_total = 24 A_SEP = 0x20 ! Separate I&D flag.! Imported variables and functions:.extern _cseg, _dseg, _runsize, _edata, _end ! Runtime environment.extern _device, _dskpars, _heads, _sectors ! Boot disk parameters.extern _eqscancode ! Ugly scancode trick.extern _rem_part ! To pass partition info.textbegtext:.extern _boot, _printk ! Boot Minix, kernel printf! Set segment registers and stack pointer using the programs own header!! The header is either 32 bytes (short form) or 48 bytes (long form). The! bootblock will jump to address 0x10030 in both cases, calling one of the! two jmpf instructions below. jmpf boot, LOADSEG+3 ! Set cs right (skipping long a.out header) .space 11 ! jmpf + 11 = 16 bytes jmpf boot, LOADSEG+2 ! Set cs right (skipping short a.out header)boot: mov ax, #LOADSEG mov ds, ax ! ds = header movb al, a_flags testb al, #A_SEP ! Separate I&D? jnz sepIDcomID: xor ax, ax xchg ax, a_text ! No text add a_data, ax ! Treat all text as datasepID: mov ax, a_total ! Total nontext memory usage and ax, #0xFFFE ! Round down to even mov a_total, ax ! total - text = data + bss + heap + stack cli ! Ignore interrupts while stack in limbo mov sp, ax ! Set sp at the top of all that mov ax, a_text ! Determine offset of ds above cs movb cl, #4 shr ax, cl mov cx, cs add ax, cx mov ds, ax ! ds = cs + text / 16 mov ss, ax sti ! Stack ok now push es ! Save es, we need it for the partition table mov es, ax cld ! C compiler wants UP! Clear bss xor ax, ax ! Zero mov di, #_edata ! Start of bss is at end of data mov cx, #_end ! End of bss (begin of heap) sub cx, di ! Number of bss bytes shr cx, #1 ! Number of words rep stos ! Clear bss! Copy primary boot parameters to variables. (Can do this now that bss is! cleared and may be written into). xorb dh, dh mov _device, dx ! Boot device (probably 0x00 or 0x80) mov _rem_part+0, si ! Remote partition table offset pop _rem_part+2 ! and segment (saved es)! Give C code access to the code segment, data segment and the size of this! process. mov _cseg, cs mov _dseg, ds push ds mov ax, #LOADSEG mov ds, ax ! Back to the header once more mov ax, a_total+0 mov dx, a_total+2 ! dx:ax = data + bss + heap + stack add ax, a_text+0 adc dx, a_text+2 ! dx:ax = text + data + bss + heap + stack pop ds mov _runsize+0, ax mov _runsize+2, dx ! 32 bit size of this process! Time to switch to a higher level language (not much higher) call _boot.define _exit, __exit, _main ! Make various compilers happy.define _reboot ! Normal reboot entry point_exit:__exit:_main:_reboot: mov ax, #any_key push ax call _printk call _getchar int 0x19.dataany_key: .ascii "\nHit any key to reboot\n\0".text! Alas we need some low level support!! void raw_copy(dstoff, dstseg, srcoff, srcseg, count)! Copy count bytes from srcseg:srcoff to dstseg:dstoff! Don't do overlaps. Count is 16 bits..define _raw_copy_raw_copy: mov bx, sp push si push di ! Save C variable registers mov cx, 10(bx) ! Count (get it before ds is trashed) les di, 2(bx) ! es:di = dstseg:dstoff lds si, 6(bx) ! ds:si = srcseg:srcoff shr cx, #1 ! Words to move jb bytecopy ! No, no, bytes! rep movw ! Do the word copy jmp copydonebytecopy: rcl cx, #1 ! Get that lost bit back rep movsb ! Do the byte copycopydone: mov ax, ss ! Restore ds and es from the remaining ss mov ds, ax mov es, ax pop di pop si ! Restore C variable registers ret! void raw_clear(off, seg, count)! Set count bytes at seg:off to zero..define _raw_clear_raw_clear: mov bx, sp push di les di, 2(bx) ! es:di = seg:off xor ax, ax ! Zero mov cx, 6(bx) ! Count shr cx, #1 ! Words to clear jb byteclear ! No, no, bytes! rep stos ! Clear jmp cleardonebyteclear: rcl cx, #1 ! Get that lost bit back rep stosb ! Byte clearcleardone: mov ax, ds ! Restore es from ds mov es, ax pop di ret! u16_t get_word(off, seg);! void put_word(off, seg, word);! Read or write a 16 bits word at an arbitrary location..define _get_word, _put_word_get_word: mov bx, sp push ds ! Save ds lds bx, 2(bx) ! ds:bx = seg:off mov ax, (bx) ! Get the word in ax pop ds ! Restore ds ret_put_word: mov bx, sp push ds mov ax, 6(bx) ! Word to store at seg:off lds bx, 2(bx) mov (bx), ax ! Store the word pop ds ret! void relocate(void);! After the program has copied itself to a safer place, it needs to change! the segment registers. Cseg has already been set to the new location..define _relocate_relocate: pop bx ! Return address mov ax, cs ! Old code segment sub ax, _cseg ! ax = -(new - old) = -Moving offset mov dx, ds sub dx, ax mov ds, dx ! ds += (new - old) mov es, dx mov ss, dx mov _dseg, dx push _cseg ! New text segment push bx ! Return offset of this function retf ! Relocate! void *brk(void *addr)! void *sbrk(size_t incr)! Cannot fail implementations of brk(2) and sbrk(3), so we can use! malloc(3). They reboot on stack collision instead of returning -1..data .align 2break: .data2 _end ! A fake heap pointer.text.define _brk, __brk, _sbrk, __sbrk_brk:__brk: ! __brk is for the standard C compiler xor ax, ax jmp sbrk ! break= 0; return sbrk(addr);_sbrk:__sbrk: mov ax, break ! ax= current breaksbrk: push ax ! save it as future return value mov bx, sp ! Stack is now: (retval, retaddr, incr, ...) add ax, 4(bx) ! ax= break + increment mov break, ax ! Set new break lea dx, -1024(bx) ! sp minus a bit of breathing space cmp dx, ax ! Compare with the new break jb heaperr ! Suffocating noises lea dx, -4096(bx) ! A warning when heap+stack goes < 4K cmp dx, ax jae plenty ! No reason to complain mov ax, #memwarn push ax call _printk ! Warn about memory running low pop ax movb memwarn, #0 ! No more warningsplenty: pop ax ! Return old break (0 for brk) retheaperr:mov ax, #chmem push ax mov ax, #nomem push ax call _printk call _reboot.datanomem: .ascii "\nOut of%s\0"memwarn:.ascii "\nLow on"chmem: .ascii " memory, use chmem to increase the heap\n\0".text! int dev_geometry(void);! Given the device "_device" and floppy disk parameters "_dskpars",! set the number of heads and sectors. It returns true iff the device! exists..define _dev_geometry_dev_geometry: movb dl, _device ! The default device cmpb dl, #0x80 ! Floppy < 0x80, winchester >= 0x80 jae winchesterfloppy: int 0x11 ! Get equipment configuration testb al, #0x01 ! Bit 0 set if floppies available jz geoerr ! No floppy drives on this box shl ax, #1 ! Highest floppy drive # in bits 6-7 shl ax, #1 ! Now in bits 0-1 of ah andb ah, #0x03 ! Extract bits cmpb dl, ah ! Must be dl <= ah for drive to exist ja geoerr ! Alas no drive dl. movb dh, #2 movb _heads, dh ! Number of heads for this device mov bx, #_dskpars ! bx = disk parameters movb cl, SECTORS(bx) movb _sectors, cl ! Sectors per track xor ax, ax mov es, ax ! es = 0 = vector segment eseg mov DSKBASE+0, bx eseg mov DSKBASE+2, ds ! DSKBASE+2:DSKBASE+0 = ds:bx = floppy parms jmp geobothwinchester: movb ah, #0x08 ! Code for drive parameters int 0x13 ! dl still contains drive jb geoerr ! No such drive? andb cl, #0x3F ! cl = max sector number (1-origin) movb _sectors, cl ! Number of sectors per track incb dh ! dh = 1 + max head number (0-origin) movb _heads, dhgeoboth: mov ax, #1 ! Code for success push ax movb al, cl ! al = sectors per track mulb dh ! ax = heads * sectors mov secspcyl, ax ! Sectors per cylinder = heads * sectorsgeodone:push ds pop es ! Restore es register pop ax ! Return code retgeoerr: xor ax, ax push ax jmp geodone.bsssecspcyl: .zerow 1.text! int readsectors(bufoff, bufseg, address, count)! int writesectors(bufoff, bufseg, address, count)! Read/write several sectors from/to disk or floppy. The buffer must! be between 64K boundaries! Count must fit in a byte. The external! variables _device, _sectors and _heads describe the disk and its! geometry. Returns 0 for success, otherwise the BIOS error code.!.define _readsectors, _writesectors_writesectors: push bp mov bp, sp movb 13(bp), #3 ! Code for a disk write jmp rwsec_readsectors: push bp mov bp, sp movb 13(bp), #2 ! Code for a disk readrwsec: push di push es les bx, 4(bp) ! es:bx = bufseg:bufoff mov di, #3 ! Execute 3 resets on floppy error cmpb _device, #0x80 jb nohd mov di, #1 ! But only 1 reset on hard disk errornohd: cmpb 12(bp), #0 ! count equals zero? jz donemore: mov ax, 8(bp) mov dx, 10(bp) ! dx:ax = address. Divide it by sectors/cyl div secspcyl ! ax = cylinder, dx = sector within cylinder xchg ax, dx ! ax = sector within cylinder, dx = cylinder movb ch, dl ! ch = low 8 bits of cylinder divb _sectors ! al = head, ah = sector (0-origin) xorb dl, dl ! About to shift bits 8-9 of cylinder into dl shr dx, #1 shr dx, #1 ! dl[6..7] = high cylinder orb dl, ah ! dl[0..5] = sector (0-origin) movb cl, dl ! cl[0..5] = sector, cl[6..7] = high cyl incb cl ! cl[0..5] = sector (1-origin) movb dh, al ! dh = head movb dl, _device ! dl = device to use movb al, _sectors ! Sectors per track - Sector number (0-origin) subb al, ah ! = Sectors left on this track cmpb al, 12(bp) ! Compare with # sectors to transfer jbe doit ! Can't go past the end of a cylinder? movb al, 12(bp) ! 12(bp) < sectors left on this trackdoit: movb ah, 13(bp) ! Code for disk read (2) or write (3) push ax ! Save al = sectors to read int 0x13 ! call the BIOS to do the transfer pop cx ! Restore al in cl jb ioerr ! I/O error movb al, cl ! Restore al = sectors read addb bh, al ! bx += 2 * al * 256 (add bytes transferred) addb bh, al ! es:bx = where next sector is located add 8(bp), ax ! Update address by sectors transferred adc 10(bp), #0 ! Don't forget high word subb 12(bp), al ! Decrement sector count by sectors transferred jnz more ! Not all sectors have been transferreddone: call wheel ! Display tricks xorb ah, ah ! No error here! jmp finishioerr: dec di ! Do we allow another reset? jl finish ! No, report the error xorb ah, ah ! Code for a reset (0) int 0x13 jae more ! Succesful reset, try request againfinish: movb al, ah xorb ah, ah ! ax = error number pop es pop di pop bp ret! int getchar(), peekchar();! Read a character from the keyboard, or just look if there is one.! A carriage return is changed into a linefeed for UNIX compatibility.! The scancode of the character '=' is saved in eqscancode if it is! typed, because it can be used to recognize an Olivetti keyboard..define _getchar, _peekchar_peekchar: movb ah, #1 ! Keyboard status
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -