BDOSLDR.A86
资源名称:drdossrc.zip [点击查看]
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:16k
源码类别:
操作系统开发
开发平台:
Asm
- ; File : $BDOSLDR.A86$
- ;
- ; Description :
- ;
- ; Original Author : DIGITAL RESEARCH
- ;
- ; Last Edited By : $CALDERA$
- ;
- ;-----------------------------------------------------------------------;
- ; Copyright Work of Caldera, Inc. All Rights Reserved.
- ;
- ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
- ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
- ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
- ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
- ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
- ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
- ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
- ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
- ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
- ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
- ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
- ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
- ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
- ; CIVIL LIABILITY.
- ;-----------------------------------------------------------------------;
- ;
- ; *** Current Edit History ***
- ; *** End of Current Edit History ***
- ;
- ; $Log$
- ;
- ; ENDLOG
- include i:reqhdr.equ
- include i:driver.equ
- include config.equ
- ; MISC constants
- CR equ 0dh ;the usual
- LF equ 0ah
- DATTS equ byte ptr 11
- DA_VOLUME equ 08h
- DA_DIR equ 10h
- DBLOCK1 equ word ptr 26
- eject
- CGROUP group INITCODE, INITDATA
- INITCODE cseg 'INITCODE'
- eject
- if DOS5
- VER_MUSTBE equ 1072h
- else
- VER_MUSTBE equ 1071h
- endif
- Public dos_version_check
- Public read_dos ; read BDOS from disk
- ;--------
- read_dos: ; read in the BDOS
- ;--------
- call login_drive ; build BPB for the boot drive
- mov si,offset dos_name ; get name of file to open
- call open_file ; open the BDOS file
- call read_file ; read in the system file
- ret
- login_drive:
- ;-----------
- les di,boot_device ; get device driver address
- mov dl,boot_drv ; get the boot drive sub unit
- mov ax,es
- or ax,di ; make sure boot device is initialised
- jnz login_drive10
- jmp dev_fail
- login_drive10:
- mov ax,es:6[di] ; get strategy offset
- mov strat_off,ax
- mov strat_seg,es ; get strategy segment
- mov ax,es:8[di] ; get interrupt offset
- mov intrpt_off,ax
- mov intrpt_seg,es ; get interrupt segment
- mov bx,offset req_hdr
- mov ds:RH_UNIT,dl ; save logical unit to use
- mov ds:RH_CMD,CMD_BUILD_BPB
- call device_request ; tell it to build a BPB
- jc dev_fail ; return if can't determine BPB
- push ds ! push si
- push ds ! pop es
- mov di,offset local_bpb ; ES:DI -> local BPB copy
- mov cx,BPB_LENGTH
- lds si,ds:RH2_BPB ; copy BPB to local memory
- rep movsb
- pop si ! pop ds
- ; Now we have to figure out whether the media uses 12 or 16 bit FATs.
- ; To that end, we need to compute the # of clusters on the drive:
- mov fat16,0 ; assume 12 bit FAT
- mov al,BT_nfats ; compute FAT size
- mov ah,0 ; AX = # of FAT copies (usually 2)
- mul BT_fat_size ; AX/DX = size of FAT in sectors
- add ax,BT_reserved_sectors ; add in bootstrap sectors
- adc dx,0
- mov cx,ax ; CX/BP = sector address of root dir
- mov bp,dx
- mov ax,32 ; compute root directory size
- mul BT_dirsize ; AX/DX = bytes in directory
- mov bx,BT_bytes_per_sector
- dec bx ; BX = sector size - 1 for rounding
- add ax,bx ; round up to next sector size
- adc dx,0
- inc bx ; BX = sector size in bytes
- div bx ; AX = # of root directory sectors
- add cx,ax ; CX/BP = sectors before data area
- adc bp,0
- mov ax,BT_total_sectors ; AX/DX = total disk size in sectors
- sub dx,dx
- test ax,ax ; is it actually larger than 65535?
- jnz dev_small ; no, AX/DX is correct
- mov ax,BT_total_long ; else get real size from extension
- mov dx,BT_total_long+2
- dev_small: ; AX/DX = disk size in sectors
- sub ax,cx ; AX/DX = data sectors
- sbb dx,bp
- ; now convert this to clusters
- mov bl,BT_sctr_per_cluster
- mov bh,0 ; BX = sectors per clusters
- div bx ; AX = # of data clusters
- inc ax
- inc ax ; cluster 0,1 are reserved
- cmp ax,0FF6h ; is this too large for 12 bits?
- jbe dev_12bit ; skip if 12 bits will do
- mov fat16,-1 ; else we use 16 bits
- dev_12bit:
- ret
- dos_version_check:
- ;-----------------
- mov ax,4452h
- int 21h ; try and get DRDOS version number
- jc dev_fail ; it's not DRDOS !
- cmp ax,VER_MUSTBE ; version check the DRDOS BDOS
- jne dev_fail ; reject all but the one we want
- ret ; return now I'm happy
- dev_fail: ; any error has occurred loading the BDOS
- ;--------
- ; Print '$' terminated message at offset DX to console without using the BDOS
- ;
- mov dx,offset dos_msg
- les di,resdev_chain ; get first device driver address
- fail_scan:
- test es:DH_ATTRIB[di],DA_CHARDEV
- jz fail_next ; skip if not a character device
- test es:DH_ATTRIB[di],DA_ISCOT
- jnz fail_found ; skip if console device found
- fail_next:
- les di,es:[di] ; get next device
- jmps fail_scan
- fail_found:
- mov ax,es:6[di] ; get strategy offset
- mov strat_off,ax
- mov strat_seg,es ; get strategy segment
- mov ax,es:8[di] ; get interrupt offset
- mov intrpt_off,ax
- mov intrpt_seg,es ; get interrupt segment
- mov bx,offset req_hdr
- mov ds:RH_CMD,CMD_OUTPUT ; write to console
- mov ds:RH_LEN,RH4_LEN ; set request header length
- mov ds:RH4_BUFOFF,dx ; set address of string
- mov ds:RH4_BUFSEG,ds
- mov ds:RH4_COUNT,-1
- mov si,dx ; now find the end of the string
- fail_count_chars:
- inc ds:RH4_COUNT ; print another char
- lodsb ; examine the next one
- cmp al,'$' ; terminating char ?
- jnz fail_count_chars
- call device_request ; call the console driver
- sti
- jmps $ ; wait for reboot
- device_request: ; general device driver interface
- ;--------------
- ; entry: BX -> request header
- ; exit: CY = 1 if error
- push ds ! push es
- push ds ! pop es
- mov ds,strat_seg
- callf cs:strat_ptr
- callf cs:intrpt_ptr
- pop es ! pop ds
- test ds:RH_STATUS,RHS_ERROR
- jnz devreq_err
- clc
- ret
- devreq_err:
- jmp dev_fail ; print error message
- ret
- open_file: ; open BDOS system file
- ;---------
- ; entry: SI -> 11 byte file name
- mov al,BT_nfats
- cbw
- mul BT_fat_size ; DX:AX = # FAT sectors
- mov cx,ax ; CX = rel_sctr dir start
- mov dx,BT_dirsize ; dx = # entries to scan
- open_f1: ; CX = current dir sector
- ; DX = current dir count
- ; SI -> file name
- push cx ! push dx ! push si
- push ds ! pop es ; ES:BX -> sector buffer
- mov bx,offset sector_buffer
- mov dx,1 ; read one directory sector
- call rd_sector_rel ; via disk driver
- pop si ! pop dx ! pop cx
- inc cx ; increment sector for next time
- sub bx,bx ; start at beginning of sector
- open_f2:
- lea di,sector_buffer[bx] ; ES:DI -> directory entry
- push si ! push di ! push cx ; save name ptr and count
- push ds ! pop es
- mov cx,11
- repe cmpsb ; check if name matches
- pop cx ! pop di ! pop si
- jne open_f3 ; skip if name doesn't match
- test DATTS[di],DA_DIR+DA_VOLUME
- jz open_foundit ; skip if matches
- open_f3:
- dec dx ; count down root directory entries
- jz open_fail ; skip if root directory done
- add bx,32 ; next entry in directory sector
- cmp bx,BT_bytes_per_sector ; sector complete?
- jb open_f2 ; loop back while more
- jmps open_f1 ; read next directory sector
- open_fail: ; file not found
- jmp dev_fail
- open_foundit: ; found the open file handle
- mov ax,DBLOCK1[di] ; get first disk block
- mov start_cluster,ax ; save starting cluster
- xor ax,ax
- ret ; return success
- read_file: ; read BDOS files into memory at MEM_CURRENT:0000
- ;---------
- mov ax,current_dos ; Get the Segment address to
- mov dta_seg,ax ; load the BDOS at
- sub ax,ax
- mov dta_off,ax
- rd_file1:
- mov cluster_count,1 ; we can read at least one cluster
- mov cx,start_cluster
- rd_file2: ; check if next cluster contiguous
- push cx ; save current cluster number
- call next_cluster ; get link to next cluster
- pop dx ; get previous cluster #
- inc dx ; is current cluster contiguous?
- cmp cx,dx ; contiguos if CX == DX
- jne rd_file3 ; no, need a separate read
- inc cluster_count ; else read one more cluster
- jmps rd_file2 ; try again with next cluster
- rd_file3: ; CX = next chain, multi cluster read
- push cx ; save start of next chain
- les bx,dta_ptr ; ES:BX -> transfer address
- mov cx,start_cluster ; previous contiguous chain starts here
- mov dx,cluster_count ; length of chain in clusters
- call rd_cluster ; read DX clusters
- mov al,BT_sctr_per_cluster
- mov ah,0 ; AX = sectors per cluster
- mul cluster_count ; AX = sectors in chain to read
- mul BT_bytes_per_sector ; AX = bytes in chain to read
- add dta_off,ax
- pop cx ; CX = next (noncontiguous) cluster
- mov start_cluster,cx ; start of new chain
- inc cx ; was it end of file cluster number?
- jnz rd_file1 ; go back for more if not
- ; else all clusters done
- ret
- get_FAT_byte:
- ;------------
- ; entry: BX = offset into FAT
- mov ax,bx ; BX = offset into FAT
- sub dx,dx ; AX/DX = 32 bit offset
- div BT_bytes_per_sector ; AX = sector, DX = offset in sector
- push dx ; save offset in sector
- call locate_FAT ; read FAT sector AX
- pop bx ; BX = offset in FAT sector
- mov al,sector_buffer[bx] ; get byte from FAT buffer
- ret
- locate_FAT:
- ;----------
- ; entry: AX = FAT sector to locate
- cmp ax,current_fatsec ; AX = sector offset into FAT
- je locate_FAT_match ; O.K. if same as last time
- mov current_fatsec,ax ; set new sector for next time
- push cx ! push si ; preserve FAT index
- mov cx,ax ; CX = sector number
- mov bx,offset sector_buffer
- push ds ! pop es ; ES:BX -> sector buffer
- mov dx,1 ; DX = single sector
- call rd_sector_rel ; read FAT sector
- pop si ! pop cx ; restore FAT index
- locate_FAT_match: ; return with right sector in buffer
- ret
- eject
- ; reads sectors relative to start of DOS area on disk (start=0)
- ; same parameters as rd_sector
- rd_sector_rel:
- ;-------------
- ; entry: CX = sector address relative to first FAT sector
- ; DX = sector count
- sub bp,bp ;overflow word = 0
- add cx,BT_reserved_sectors
- adc bp,0
- ; jmps rd_sector
- ; reads absolute sectors from hard disk using rom bios
- rd_sector:
- ;---------
- ; entry: DX = number of sectors
- ; ES:BX -> data transfer buffer
- ; DS -> program global data segment
- ; CX/BP = absolute sector # (32 bit) (low/high)
- push cx ! push dx ; save parameters
- mov req3_bufoff,bx ; save transfer offset
- mov req3_bufseg,es ; save transfer segment
- mov req3_count,dx ; set sector count
- mov bx,offset req_hdr ; BX -> request header
- mov ds:RH_CMD,CMD_INPUT ; read from disk device
- mov req3_sector,cx ; set requested sector address
- if DOS5
- mov req_hdr,RH4_LEN
- mov req3_sector32,cx ; with 32 sector number
- mov req3_sector32+2,bp
- test bp,bp ; large sector number?
- jz rd_sec1 ; no, normal request header
- mov req3_sector,0FFFFh ; mark as a large request
- rd_sec1:
- else
- mov req3_sector+2,bp ; (support large DOS drives)
- mov req_hdr,24 ; indicate large request
- endif
- call device_request ; tell it to read sectors
- pop cx ! pop dx
- ret ; if CY, AH=error code
- rd_cluster:
- ;----------
- ; entry: CX = DOS cluster number.
- ; DX = cluster count
- ; ES:BX -> transfer buffer
- push bx ! push es
- mov al,BT_sctr_per_cluster
- mov ah,0 ; AX = sectors per cluster
- mul dx ; AX = sectors in all clusters
- push ax ; save the sector count
- sub cx,2 ; cluster 2 is data area start
- mov al,BT_sctr_per_cluster
- cbw
- mul cx ; AX,DX = relative sector #
- mov cx,ax
- mov bp,dx ; CX,BP = data area sector #
- mov al,BT_nfats ; compute FAT size
- mov ah,0 ; AX = # of FAT copies (usually 2)
- mul BT_fat_size ; AX/DX = size of FAT in sectors
- add cx,ax
- adc bp,dx ; CX,BP = end of FAT sectors
- mov ax,32
- mul BT_dirsize ; AX,DX = bytes in root directory
- mov bx,BT_bytes_per_sector
- dec bx
- add ax,bx ; round up directory size
- adc dx,0
- inc bx
- div bx ; AX = root directory sectors
- add cx,ax
- adc bp,0 ; add root directory size
- add cx,BT_reserved_sectors ; add in boot sector(s)
- adc bp,0
- pop dx ! pop es ! pop bx ; sector count, disk address
- jmp rd_sector ; DX secs from CX/BP to ES:BX
- ; Finds the NEXT cluster after the one passed in CX in an allocation
- ; chain by using the FAT. Returns the carry set if the end of chain
- ; mark is found, otherwise returns the NEW cluster # in CX.
- next_cluster:
- ;------------
- push dx ! push bx ; save some registers
- cmp fat16,0 ; check if this is 12 bit media
- je next_cluster12 ; skip if old fashioned 12 bit
- mov ax,2
- mul cx ; AX/DX = byte offset in FAT (max. 128K)
- div BT_bytes_per_sector ; AX = FAT sector #, DX = byte offset
- push dx ; save byte offset within sector
- call locate_FAT ; get FAT sector AX
- pop bx ; BX = offset within sector
- mov cx,word ptr sector_buffer[bx]
- ; get 16 bit from FAT
- cmp cx,0FFF7h ; check if too large for #
- jae next_cluster_eof ; set carry, EOF
- clc
- jmps next_cluster_ret ; good link
- next_cluster12: ; DOS 2.x disk
- push cx ; save cluster number
- mov bx,cx
- add bx,bx ; BX = cluster# * 2
- add bx,cx ; BX = cluster# * 3
- shr bx,1 ; BX = cluster# * 1.5
- push bx ; save offset in the FAT
- inc bx ; BX = offset of high byte
- call get_FAT_byte ; get the high byte in AL
- pop bx ; BX = offset of low byte
- push ax ; save high byte on stack
- call get_FAT_byte ; get the low byte in AL
- pop bx ; pop off high byte into BL
- mov ah,bl ; set high byte, AX = word
- pop cx ; restore cluster number
- shr cx,1 ; test if even or odd
- jnc even_fat ; if even entry, done
- mov cl,4 ; odd entry, shift down one nibble
- shr ax,cl ; else need to justify
- even_fat: ; even entry, strip off top bits
- and ax,0fffh ; bx[0..11] are cluster
- mov cx,ax ; CX = cluster number
- cmp cx,0ff7h ; compare with largest legal 12 bit #
- jae next_cluster_eof ; check for end mark
- clc
- jmps next_cluster_ret ; return value in CX, CY = 0
- next_cluster_eof:
- mov cx,-1 ; indicate end of chain
- stc ; end of chain
- next_cluster_ret:
- pop bx ! pop dx
- ret
- eject
- ;
- ; INITIALIZED DATA SEGMENT
- ; ========================
- INITDATA dseg 'INITDATA'
- extrn resdev_chain:dword ; resident device driver root
- extrn current_dos:word ; current BDOS segment
- extrn boot_device:dword ; device driver we boot from
- extrn boot_drv:byte ; boot drive
- extrn dos_name:byte ; name of BDOS file
- strat_ptr rd 0
- strat_off rw 1
- strat_seg rw 1
- intrpt_ptr rd 0
- intrpt_off rw 1
- intrpt_seg rw 1
- dta_ptr rd 0
- dta_off rw 1
- dta_seg rw 1
- start_cluster rw 1
- cluster_count rw 1
- current_fatsec dw -1 ; no FAT sector read yet
- fat16 dw 0 ; defaults to 12 bit FAT
- ; single error message if BDOS can't be loaded:
- include initmsgs.def ; Include TFT Header File
- ;dos_msg db CR,LF,'Can''t load DOS file.$'
- ; static request header for DOS device driver I/O
- req_hdr db 22
- req_unit rb 1
- req_cmd rb 1
- req_status rw 1
- rd 2
- req_media rb 1
- rb 16
- req1_return equ byte ptr req_media+1
- req1_volid equ word ptr req_media+2
- req2_bufoff equ word ptr req_media+1
- req2_bufseg equ word ptr req_media+3
- req2_bpb equ word ptr req_media+5
- req3_buffer equ dword ptr req_media+1
- req3_bufoff equ word ptr req_media+1
- req3_bufseg equ word ptr req_media+3
- req3_count equ word ptr req_media+5
- req3_sector equ word ptr req_media+7
- req3_volid equ word ptr req_media+9
- req3_sector32 equ word ptr req_media+13
- ; local copy of the BPB for the boot device
- local_bpb rb 0
- BT_bytes_per_sector rw 1
- BT_sctr_per_cluster rb 1
- BT_reserved_sectors rw 1
- BT_nfats rb 1
- BT_dirsize rw 1
- BT_total_sectors rw 1
- BT_fatid rb 1
- BT_fat_size rw 1
- BT_sectors_per_track rw 1
- BT_nheads rw 1
- BT_hidden_sectors rw 2
- BT_total_long rw 2
- BPB_LENGTH equ (offset $-offset local_bpb)
- extrn sector_buffer:byte
- end