📄 bdosldr.a86
字号:
; 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -