📄 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: o32 = 0x66 ! This assembler doesn't know 386 extensions 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 K_I386 = 0x0001 ! Call Minix in 386 mode K_RET = 0x0020 ! Returns to the monitor on reboot DS_SELECTOR = 3*8 ! Kernel data selector ES_SELECTOR = 4*8 ! Flat 4 Gb SS_SELECTOR = 5*8 ! Monitor stack CS_SELECTOR = 6*8 ! Kernel code MCS_SELECTOR= 7*8 ! Monitor code! Imported variables and functions:.extern _caddr, _daddr, _runsize, _edata, _end ! Runtime environment.extern _device, _dskpars, _heads, _sectors ! Boot disk parameters.extern _rem_part ! To pass partition info.extern _k_flags ! Special kernel flags.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)! Remember the current video mode for restoration on exit. movb ah, #0x0F ! Get current video mode int 0x10 andb al, #0x7F ! Mask off bit 7 (no blanking) movb old_vid_mode, al movb cur_vid_mode, al! Give C code access to the code segment, data segment and the size of this! process. xor ax, ax mov dx, cs call seg2abs mov _caddr+0, ax mov _caddr+2, dx xor ax, ax mov dx, ds call seg2abs mov _daddr+0, ax mov _daddr+2, dx 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 add ax, #0x000F adc dx, #0 and ax, #0xFFF0 ! Round up to a segment 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, ___exit ! Make various compilers happy_exit:__exit:___exit: mov bx, sp cmp 2(bx), #0 ! Good exit status? jz rebootquit: mov ax, #any_key push ax call _printk call _getcharreboot: call restore_video int 0x19 ! Reboot the system.dataany_key: .ascii "\nHit any key to reboot\n\0".text! Alas we need some low level support!! u32_t mon2abs(void *ptr)! Address in monitor data to absolute address..define _mon2abs_mon2abs: mov bx, sp mov ax, 2(bx) ! ptr mov dx, ds ! Monitor data segment jmp seg2abs! u32_t vec2abs(vector *vec)! 8086 interrupt vector to absolute address..define _vec2abs_vec2abs: mov bx, sp mov bx, 2(bx) mov ax, (bx) mov dx, 2(bx) ! dx:ax vector !jmp seg2abs ! Translateseg2abs: ! Translate dx:ax to the 32 bit address dx-ax push cx movb ch, dh movb cl, #4 shl dx, cl shrb ch, cl ! ch-dx = dx << 4 add ax, dx adcb ch, #0 ! ch-ax = ch-dx + ax movb dl, ch xorb dh, dh ! dx-ax = ch-ax pop cx retabs2seg: ! Translate the 32 bit address dx-ax to dx:ax push cx movb ch, dl mov dx, ax ! ch-dx = dx-ax and ax, #0x000F ! Offset in ax movb cl, #4 shr dx, cl shlb ch, cl orb dh, ch ! dx = ch-dx >> 4 pop cx ret! void raw_copy(u32_t dstaddr, u32_t srcaddr, u32_t count)! Copy count bytes from srcaddr to dstaddr. Don't do overlaps.! Also handles copying words to or from extended memory..define _raw_copy_raw_copy: push bp mov bp, sp push si push di ! Save C variable registerscopy: cmp 14(bp), #0 jnz bigcopy mov cx, 12(bp) jcxz copydone ! Count is zero, end copy cmp cx, #0xFFF0 jb smallcopybigcopy:mov cx, #0xFFF0 ! Don't copy more than about 64K at oncesmallcopy: push cx ! Save copying count mov ax, 4(bp) mov dx, 6(bp) cmp dx, #0x0010 ! Copy to extended memory? jae ext_copy cmp 10(bp), #0x0010 ! Copy from extended memory? jae ext_copy call abs2seg mov di, ax mov es, dx ! es:di = dstaddr mov ax, 8(bp) mov dx, 10(bp) call abs2seg mov si, ax mov ds, dx ! ds:si = srcaddr shr cx, #1 ! Words to move rep movs ! Do the word copy adc cx, cx ! One more byte? rep movsb ! Do the byte copy mov ax, ss ! Restore ds and es from the remaining ss mov ds, ax mov es, ax jmp copyadjustext_copy: mov x_dst_desc+2, ax movb x_dst_desc+4, dl ! Set base of destination segment mov ax, 8(bp) mov dx, 10(bp) mov x_src_desc+2, ax movb x_src_desc+4, dl ! Set base of source segment mov si, #x_gdt ! es:si = global descriptor table shr cx, #1 ! Words to move movb ah, #0x87 ! Code for extended memory move int 0x15copyadjust: pop cx ! Restore count add 4(bp), cx adc 6(bp), #0 ! srcaddr += copycount add 8(bp), cx adc 10(bp), #0 ! dstaddr += copycount sub 12(bp), cx sbb 14(bp), #0 ! count -= copycount jmp copy ! and repeatcopydone: pop di pop si ! Restore C variable registers pop bp ret! u16_t get_word(u32_t addr);! void put_word(u32_t addr, u16_t word);! Read or write a 16 bits word at an arbitrary location..define _get_word, _put_word_get_word: mov bx, sp call gp_getaddr mov ax, (bx) ! Word to get from addr jmp gp_ret_put_word: mov bx, sp push 6(bx) ! Word to store at addr call gp_getaddr pop (bx) ! Store the word jmp gp_retgp_getaddr: mov ax, 2(bx) mov dx, 4(bx) call abs2seg mov bx, ax mov ds, dx ! ds:bx = addr retgp_ret: push es pop ds ! Restore ds ret! void relocate(void);! After the program has copied itself to a safer place, it needs to change! the segment registers. Caddr has already been set to the new location..define _relocate_relocate: pop bx ! Return address mov ax, _caddr+0 mov dx, _caddr+2 call abs2seg mov cx, dx ! cx = new code segment mov ax, cs ! Old code segment sub ax, cx ! ax = -(new - old) = -Moving offset mov dx, ds sub dx, ax mov ds, dx ! ds += (new - old) mov es, dx mov ss, dx xor ax, ax call seg2abs mov _daddr+0, ax mov _daddr+2, dx ! New data address push cx ! 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 jmp quit.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: push es push di ! Save registers used by BIOS calls 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 ! Floppies have two sides mov bx, #_dskpars ! bx = disk parameters movb cl, SECTORS(bx) 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) incb dh ! dh = 1 + max head number (0-origin)geoboth: movb _heads, dh ! Number of heads for this device movb _sectors, cl ! Sectors per track movb al, cl ! al = sectors per track mulb dh ! ax = heads * sectors mov secspcyl, ax ! Sectors per cylinder = heads * sectors mov ax, #1 ! Code for successgeodone: pop di pop es ! Restore di and es registers retgeoerr: xor ax, ax ! Code for failure jmp geodone.bsssecspcyl: .space 1*2.text! int readsectors(u32_t bufaddr, u32_t sector, u8_t count)! int writesectors(u32_t bufaddr, u32_t sector, u8_t 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 mov ax, 4(bp) mov dx, 6(bp) call abs2seg mov bx, ax mov es, dx ! es:bx = bufaddr 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 = abs sector. 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: xorb ah, ah ! No error here! jmp finishioerr: cmpb ah, #0x80 ! Disk timed out? (Floppy drive empty) je finish cmpb ah, #0x03 ! Disk write protected? je finish dec di ! Do we allow another reset? jl finish ! No, report the error xorb ah, ah ! Code for a reset (0) int 0x13 jnb more ! Succesful reset, try request againfinish: movb al, ah xorb ah, ah ! ax = error number pop es pop di pop bp ret! int getchar(void), peekchar(void);! Read a character from the keyboard, or just look if there is one.! A carriage return is changed into a linefeed for UNIX compatibility..define _getchar, _peekchar
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -