BDOSLDR.A86
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:16k
源码类别:

操作系统开发

开发平台:

Asm

  1. ;    File              : $BDOSLDR.A86$
  2. ;
  3. ;    Description       :
  4. ;
  5. ;    Original Author   : DIGITAL RESEARCH
  6. ;
  7. ;    Last Edited By    : $CALDERA$
  8. ;
  9. ;-----------------------------------------------------------------------;
  10. ;    Copyright Work of Caldera, Inc. All Rights Reserved.
  11. ;      
  12. ;    THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
  13. ;    PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
  14. ;    ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
  15. ;    WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
  16. ;    THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
  17. ;    HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
  18. ;    AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
  19. ;    AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
  20. ;    COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
  21. ;    CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
  22. ;    TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
  23. ;    CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
  24. ;    AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
  25. ;    CIVIL LIABILITY.
  26. ;-----------------------------------------------------------------------;
  27. ;
  28. ;    *** Current Edit History ***
  29. ;    *** End of Current Edit History ***
  30. ;
  31. ;    $Log$
  32. ;
  33. ;    ENDLOG
  34. include i:reqhdr.equ
  35. include i:driver.equ
  36. include config.equ
  37. ; MISC constants
  38. CR equ 0dh ;the usual
  39. LF equ 0ah
  40. DATTS equ byte ptr 11
  41.  DA_VOLUME equ 08h
  42.  DA_DIR equ 10h
  43. DBLOCK1 equ word ptr 26
  44. eject
  45. CGROUP group INITCODE, INITDATA
  46. INITCODE cseg 'INITCODE'
  47. eject
  48. if DOS5
  49. VER_MUSTBE equ 1072h
  50. else
  51. VER_MUSTBE equ 1071h
  52. endif
  53. Public dos_version_check
  54. Public read_dos ; read BDOS from disk
  55. ;--------
  56. read_dos: ; read in the BDOS
  57. ;--------
  58. call login_drive ; build BPB for the boot drive
  59. mov si,offset dos_name ; get name of file to open
  60. call open_file ; open the BDOS file
  61. call read_file ; read in the system file
  62. ret
  63. login_drive:
  64. ;-----------
  65. les di,boot_device ; get device driver address
  66. mov dl,boot_drv ; get the boot drive sub unit
  67. mov ax,es
  68. or ax,di ; make sure boot device is initialised
  69.  jnz login_drive10
  70. jmp dev_fail
  71. login_drive10:
  72. mov ax,es:6[di] ; get strategy offset
  73. mov strat_off,ax
  74. mov strat_seg,es ; get strategy segment
  75. mov ax,es:8[di] ; get interrupt offset
  76. mov intrpt_off,ax
  77. mov intrpt_seg,es ; get interrupt segment
  78. mov bx,offset req_hdr
  79. mov ds:RH_UNIT,dl ; save logical unit to use
  80. mov ds:RH_CMD,CMD_BUILD_BPB
  81. call device_request ; tell it to build a BPB
  82.  jc dev_fail ; return if can't determine BPB
  83. push ds ! push si
  84. push ds ! pop es
  85. mov di,offset local_bpb ; ES:DI -> local BPB copy
  86. mov cx,BPB_LENGTH
  87. lds si,ds:RH2_BPB ; copy BPB to local memory
  88. rep movsb
  89. pop si ! pop ds
  90. ; Now we have to figure out whether the media uses 12 or 16 bit FATs.
  91. ; To that end, we need to compute the # of clusters on the drive:
  92. mov fat16,0 ; assume 12 bit FAT
  93. mov al,BT_nfats ; compute FAT size
  94. mov ah,0 ; AX = # of FAT copies (usually 2)
  95. mul BT_fat_size ; AX/DX = size of FAT in sectors
  96. add ax,BT_reserved_sectors ; add in bootstrap sectors
  97. adc dx,0
  98. mov cx,ax ; CX/BP = sector address of root dir
  99. mov bp,dx
  100. mov ax,32 ; compute root directory size
  101. mul BT_dirsize ; AX/DX = bytes in directory
  102. mov bx,BT_bytes_per_sector
  103. dec bx ; BX = sector size - 1 for rounding
  104. add ax,bx ; round up to next sector size
  105. adc dx,0
  106. inc bx ; BX = sector size in bytes
  107. div bx ; AX = # of root directory sectors
  108. add cx,ax ; CX/BP = sectors before data area
  109. adc bp,0
  110. mov ax,BT_total_sectors ; AX/DX = total disk size in sectors
  111. sub dx,dx
  112. test ax,ax ; is it actually larger than 65535?
  113.  jnz dev_small ; no, AX/DX is correct
  114. mov ax,BT_total_long ; else get real size from extension
  115. mov dx,BT_total_long+2
  116. dev_small: ; AX/DX = disk size in sectors
  117. sub ax,cx ; AX/DX = data sectors
  118. sbb dx,bp
  119. ; now convert this to clusters
  120. mov bl,BT_sctr_per_cluster
  121. mov bh,0 ; BX = sectors per clusters
  122. div bx ; AX = # of data clusters
  123. inc ax
  124. inc ax ; cluster 0,1 are reserved
  125. cmp ax,0FF6h ; is this too large for 12 bits?
  126.  jbe dev_12bit ; skip if 12 bits will do
  127. mov fat16,-1 ; else we use 16 bits
  128. dev_12bit:
  129. ret
  130. dos_version_check:
  131. ;-----------------
  132. mov ax,4452h
  133. int 21h ; try and get DRDOS version number
  134.  jc dev_fail ;  it's not DRDOS !
  135. cmp ax,VER_MUSTBE ; version check the DRDOS BDOS
  136.  jne dev_fail ;  reject all but the one we want
  137. ret ; return now I'm happy
  138. dev_fail: ; any error has occurred loading the BDOS
  139. ;--------
  140. ; Print '$' terminated message at offset DX to console without using the BDOS
  141. ;
  142. mov dx,offset dos_msg
  143. les di,resdev_chain ; get first device driver address
  144. fail_scan:
  145. test es:DH_ATTRIB[di],DA_CHARDEV
  146.  jz fail_next ; skip if not a character device
  147. test es:DH_ATTRIB[di],DA_ISCOT
  148.  jnz fail_found ; skip if console device found
  149. fail_next:
  150. les di,es:[di] ; get next device
  151. jmps fail_scan
  152. fail_found:
  153. mov ax,es:6[di] ; get strategy offset
  154. mov strat_off,ax
  155. mov strat_seg,es ; get strategy segment
  156. mov ax,es:8[di] ; get interrupt offset
  157. mov intrpt_off,ax
  158. mov intrpt_seg,es ; get interrupt segment
  159. mov bx,offset req_hdr
  160. mov ds:RH_CMD,CMD_OUTPUT ; write to console
  161. mov ds:RH_LEN,RH4_LEN ; set request header length
  162. mov ds:RH4_BUFOFF,dx ; set address of string
  163. mov ds:RH4_BUFSEG,ds
  164. mov ds:RH4_COUNT,-1
  165. mov si,dx ; now find the end of the string
  166. fail_count_chars:
  167. inc ds:RH4_COUNT ; print another char
  168. lodsb ; examine the next one
  169. cmp al,'$' ; terminating char ?
  170.  jnz fail_count_chars
  171. call device_request ; call the console driver
  172. sti
  173. jmps $ ; wait for reboot
  174. device_request: ; general device driver interface
  175. ;--------------
  176. ; entry: BX -> request header
  177. ; exit: CY = 1 if error
  178. push ds ! push es
  179. push ds ! pop es
  180. mov ds,strat_seg
  181. callf cs:strat_ptr
  182. callf cs:intrpt_ptr
  183. pop es ! pop ds
  184. test ds:RH_STATUS,RHS_ERROR
  185.  jnz devreq_err
  186. clc
  187. ret
  188. devreq_err:
  189. jmp dev_fail ; print error message
  190. ret
  191. open_file: ; open BDOS system file
  192. ;---------
  193. ; entry: SI -> 11 byte file name
  194. mov al,BT_nfats
  195. cbw
  196. mul BT_fat_size ; DX:AX = # FAT sectors
  197. mov cx,ax ; CX = rel_sctr dir start
  198. mov dx,BT_dirsize ; dx = # entries to scan
  199. open_f1:  ; CX = current dir sector
  200. ; DX = current dir count
  201. ; SI -> file name
  202. push cx ! push dx ! push si
  203. push ds ! pop es ; ES:BX -> sector buffer
  204. mov bx,offset sector_buffer
  205. mov dx,1 ; read one directory sector
  206. call rd_sector_rel ;     via disk driver
  207. pop si ! pop dx ! pop cx
  208. inc cx ; increment sector for next time
  209. sub bx,bx ; start at beginning of sector
  210. open_f2:
  211. lea di,sector_buffer[bx] ; ES:DI -> directory entry
  212. push si ! push di ! push cx ; save name ptr and count
  213. push ds ! pop es
  214. mov cx,11
  215. repe cmpsb ; check if name matches
  216. pop cx ! pop di ! pop si
  217.  jne open_f3 ; skip if name doesn't match
  218. test DATTS[di],DA_DIR+DA_VOLUME
  219.  jz open_foundit ; skip if matches
  220. open_f3:
  221. dec dx ; count down root directory entries
  222.  jz open_fail ; skip if root directory done
  223. add bx,32 ; next entry in directory sector
  224. cmp bx,BT_bytes_per_sector ; sector complete?
  225.  jb open_f2 ; loop back while more
  226. jmps open_f1 ; read next directory sector
  227. open_fail: ; file not found
  228. jmp dev_fail
  229. open_foundit: ; found the open file handle
  230. mov ax,DBLOCK1[di] ; get first disk block
  231. mov start_cluster,ax ; save starting cluster
  232. xor ax,ax
  233. ret ; return success
  234. read_file: ; read BDOS files into memory at MEM_CURRENT:0000
  235. ;---------
  236. mov ax,current_dos ; Get the Segment address to
  237. mov dta_seg,ax ; load the BDOS at
  238. sub ax,ax
  239. mov dta_off,ax
  240. rd_file1:
  241. mov cluster_count,1 ; we can read at least one cluster
  242. mov cx,start_cluster
  243. rd_file2: ; check if next cluster contiguous
  244. push cx ; save current cluster number
  245. call next_cluster ; get link to next cluster
  246. pop dx ; get previous cluster #
  247. inc dx ; is current cluster contiguous?
  248. cmp cx,dx ; contiguos if CX == DX
  249.  jne rd_file3 ; no, need a separate read
  250. inc cluster_count ; else read one more cluster
  251. jmps rd_file2 ; try again with next cluster
  252. rd_file3: ; CX = next chain, multi cluster read
  253. push cx ; save start of next chain
  254. les bx,dta_ptr ; ES:BX -> transfer address
  255. mov cx,start_cluster ; previous contiguous chain starts here
  256. mov dx,cluster_count ; length of chain in clusters
  257. call rd_cluster ; read DX clusters
  258. mov al,BT_sctr_per_cluster
  259. mov ah,0 ; AX = sectors per cluster
  260. mul cluster_count ; AX = sectors in chain to read
  261. mul BT_bytes_per_sector ; AX = bytes in chain to read
  262. add dta_off,ax
  263. pop cx ; CX = next (noncontiguous) cluster
  264. mov start_cluster,cx ; start of new chain
  265. inc cx ; was it end of file cluster number?
  266.  jnz rd_file1 ; go back for more if not
  267. ; else all clusters done
  268. ret
  269. get_FAT_byte:
  270. ;------------
  271. ; entry: BX = offset into FAT
  272. mov ax,bx ; BX = offset into FAT
  273. sub dx,dx ; AX/DX = 32 bit offset
  274. div BT_bytes_per_sector ; AX = sector, DX = offset in sector
  275. push dx ; save offset in sector
  276. call locate_FAT ; read FAT sector AX
  277. pop bx ; BX = offset in FAT sector
  278. mov al,sector_buffer[bx] ; get byte from FAT buffer
  279. ret
  280. locate_FAT:
  281. ;----------
  282. ; entry: AX = FAT sector to locate
  283. cmp ax,current_fatsec ; AX = sector offset into FAT
  284.  je locate_FAT_match ; O.K. if same as last time
  285. mov current_fatsec,ax ; set new sector for next time
  286. push cx ! push si ; preserve FAT index
  287. mov cx,ax ; CX = sector number
  288. mov bx,offset sector_buffer
  289. push ds ! pop es ; ES:BX -> sector buffer
  290. mov dx,1 ; DX = single sector
  291. call rd_sector_rel ; read FAT sector
  292. pop si ! pop cx ; restore FAT index
  293. locate_FAT_match: ; return with right sector in buffer
  294. ret
  295. eject
  296. ; reads sectors relative to start of DOS area on disk (start=0)
  297. ; same parameters as rd_sector
  298. rd_sector_rel:
  299. ;-------------
  300. ; entry: CX = sector address relative to first FAT sector
  301. ; DX = sector count
  302. sub bp,bp ;overflow word = 0
  303. add cx,BT_reserved_sectors
  304. adc bp,0
  305. ; jmps rd_sector
  306. ; reads absolute sectors from hard disk using rom bios
  307. rd_sector:
  308. ;---------
  309. ; entry: DX = number of sectors
  310. ; ES:BX -> data transfer buffer
  311. ; DS -> program global data segment
  312. ; CX/BP = absolute sector # (32 bit) (low/high)
  313. push cx ! push dx ; save parameters
  314. mov req3_bufoff,bx ; save transfer offset
  315. mov req3_bufseg,es ; save transfer segment
  316. mov req3_count,dx ; set sector count
  317. mov bx,offset req_hdr ; BX -> request header
  318. mov ds:RH_CMD,CMD_INPUT ; read from disk device
  319. mov req3_sector,cx ; set requested sector address
  320. if DOS5
  321. mov req_hdr,RH4_LEN
  322. mov req3_sector32,cx ;  with 32 sector number
  323. mov req3_sector32+2,bp
  324. test bp,bp ; large sector number?
  325.  jz rd_sec1 ; no, normal request header
  326. mov req3_sector,0FFFFh ; mark as a large request
  327. rd_sec1:
  328. else
  329. mov req3_sector+2,bp ; (support large DOS drives)
  330. mov req_hdr,24 ; indicate large request
  331. endif
  332. call device_request ; tell it to read sectors
  333. pop cx ! pop dx
  334. ret ; if CY, AH=error code
  335. rd_cluster:
  336. ;----------
  337. ; entry: CX = DOS cluster number.
  338. ; DX = cluster count
  339. ; ES:BX -> transfer buffer
  340. push bx ! push es
  341. mov al,BT_sctr_per_cluster
  342. mov ah,0 ; AX = sectors per cluster
  343. mul dx ; AX = sectors in all clusters
  344. push ax ; save the sector count
  345. sub cx,2 ; cluster 2 is data area start
  346. mov al,BT_sctr_per_cluster
  347. cbw
  348. mul cx ; AX,DX = relative sector #
  349. mov cx,ax
  350. mov bp,dx ; CX,BP = data area sector #
  351. mov al,BT_nfats ; compute FAT size
  352. mov ah,0 ; AX = # of FAT copies (usually 2)
  353. mul BT_fat_size ; AX/DX = size of FAT in sectors
  354. add cx,ax
  355. adc bp,dx ; CX,BP = end of FAT sectors
  356. mov ax,32
  357. mul BT_dirsize ; AX,DX = bytes in root directory
  358. mov bx,BT_bytes_per_sector
  359. dec bx
  360. add ax,bx ; round up directory size
  361. adc dx,0
  362. inc bx
  363. div bx ; AX = root directory sectors
  364. add cx,ax
  365. adc bp,0 ; add root directory size
  366. add cx,BT_reserved_sectors ; add in boot sector(s)
  367. adc bp,0
  368. pop dx ! pop es ! pop bx ; sector count, disk address
  369. jmp rd_sector ; DX secs from CX/BP to ES:BX
  370. ; Finds the NEXT cluster after the one passed in CX in an allocation
  371. ; chain by using the FAT.  Returns the carry set if the end of chain
  372. ; mark is found, otherwise returns the NEW cluster # in CX.
  373. next_cluster:
  374. ;------------
  375. push dx ! push bx ; save some registers
  376. cmp fat16,0 ; check if this is 12 bit media
  377.  je next_cluster12 ; skip if old fashioned 12 bit
  378. mov ax,2
  379. mul cx ; AX/DX = byte offset in FAT (max. 128K)
  380. div BT_bytes_per_sector ; AX = FAT sector #, DX = byte offset
  381. push dx ; save byte offset within sector
  382. call locate_FAT ; get FAT sector AX
  383. pop bx ; BX = offset within sector
  384. mov cx,word ptr sector_buffer[bx]
  385. ; get 16 bit from FAT
  386. cmp cx,0FFF7h ; check if too large for #
  387.  jae next_cluster_eof ; set carry, EOF
  388. clc
  389. jmps next_cluster_ret ; good link
  390. next_cluster12: ; DOS 2.x disk
  391. push cx ; save cluster number
  392. mov bx,cx
  393. add bx,bx ; BX = cluster# * 2
  394. add bx,cx ; BX = cluster# * 3
  395. shr bx,1 ; BX = cluster# * 1.5
  396. push bx ; save offset in the FAT
  397. inc bx ; BX = offset of high byte
  398. call get_FAT_byte ; get the high byte in AL
  399. pop bx ; BX = offset of low byte
  400. push ax ; save high byte on stack
  401. call get_FAT_byte ; get the low byte in AL
  402. pop bx ; pop off high byte into BL
  403. mov ah,bl ; set high byte, AX = word
  404. pop cx ; restore cluster number
  405. shr cx,1 ; test if even or odd
  406.  jnc even_fat ; if even entry, done
  407. mov cl,4 ; odd entry, shift down one nibble
  408. shr ax,cl ; else need to justify
  409. even_fat: ; even entry, strip off top bits
  410. and ax,0fffh ; bx[0..11] are cluster
  411. mov cx,ax ; CX = cluster number
  412. cmp cx,0ff7h ; compare with largest legal 12 bit #
  413.  jae next_cluster_eof ; check for end mark
  414. clc
  415. jmps next_cluster_ret ; return value in CX, CY = 0
  416. next_cluster_eof:
  417. mov cx,-1 ; indicate end of chain
  418. stc ; end of chain
  419. next_cluster_ret:
  420. pop bx ! pop dx
  421. ret
  422. eject
  423. ;
  424. ; INITIALIZED DATA SEGMENT
  425. ; ========================
  426. INITDATA dseg 'INITDATA'
  427. extrn resdev_chain:dword ; resident device driver root
  428. extrn current_dos:word ; current BDOS segment
  429. extrn boot_device:dword ; device driver we boot from
  430. extrn boot_drv:byte ; boot drive
  431. extrn dos_name:byte ; name of BDOS file
  432. strat_ptr rd 0
  433. strat_off rw 1
  434. strat_seg rw 1
  435. intrpt_ptr rd 0
  436. intrpt_off rw 1
  437. intrpt_seg rw 1
  438. dta_ptr rd 0
  439. dta_off rw 1
  440. dta_seg rw 1
  441. start_cluster rw 1
  442. cluster_count rw 1
  443. current_fatsec dw -1 ; no FAT sector read yet
  444. fat16 dw 0 ; defaults to 12 bit FAT
  445. ; single error message if BDOS can't be loaded:
  446. include initmsgs.def ; Include TFT Header File
  447. ;dos_msg db CR,LF,'Can''t load DOS file.$'
  448. ; static request header for DOS device driver I/O
  449. req_hdr db 22
  450. req_unit rb 1
  451. req_cmd rb 1
  452. req_status rw 1
  453. rd 2
  454. req_media rb 1
  455. rb 16
  456. req1_return equ byte ptr req_media+1
  457. req1_volid equ word ptr req_media+2
  458. req2_bufoff equ word ptr req_media+1
  459. req2_bufseg equ word ptr req_media+3
  460. req2_bpb equ word ptr req_media+5
  461. req3_buffer equ dword ptr req_media+1
  462. req3_bufoff equ word ptr req_media+1
  463. req3_bufseg equ word ptr req_media+3
  464. req3_count equ word ptr req_media+5
  465. req3_sector equ word ptr req_media+7
  466. req3_volid equ word ptr req_media+9
  467. req3_sector32 equ word ptr req_media+13
  468. ; local copy of the BPB for the boot device
  469. local_bpb rb 0
  470. BT_bytes_per_sector rw 1
  471. BT_sctr_per_cluster rb 1
  472. BT_reserved_sectors rw 1
  473. BT_nfats rb 1
  474. BT_dirsize rw 1
  475. BT_total_sectors rw 1
  476. BT_fatid rb 1
  477. BT_fat_size rw 1
  478. BT_sectors_per_track  rw 1
  479. BT_nheads rw 1
  480. BT_hidden_sectors rw 2
  481. BT_total_long rw 2
  482. BPB_LENGTH equ (offset $-offset local_bpb)
  483. extrn sector_buffer:byte
  484. end