DOS 3.30 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1167 lines
26 KiB

5 years ago
  1. ; SCCSID = @(#)sys.asm 1.12 85/10/06
  2. TITLE MS-DOS SYS Program
  3. ; SYS - Copies system programs IBMBIO.COM/IO.SYS and IBMDOS.COM/MSDOS.SYS
  4. ; 1.6 05/21/82 Added rev number message
  5. ; 1.61 06/04/82 Allow SYS to blank disk TimP at SCP
  6. ; 1.70 06/30/82 NON contiguous DOS allowed on 2.00 IBM. Allows SYS to
  7. ; 1.0 1.1 disks.
  8. ; 1.71 07/02/82 Put in CHDIRs to make sure everything done in root dir.
  9. ; 1.80 04/26/83 MZ make sys work in small machines; use full 2.0
  10. ; system calls
  11. ; 1.81 07/22/83 ARR Added check in IBM version for valid FAT ID on
  12. ; destination because of IBM problem with SYSing to
  13. ; unformatted disks which are really formatted. Prints
  14. ; NoDest message for ridic IBM reasons, should have a
  15. ; better message.
  16. ; 1.82 08/12/83 ARR ZIBOed again. Mark fails to check for errors on
  17. ; his file I/O. Results in SYS saying system
  18. ; transferred when it hasn't been.
  19. ; 1.83 09/08/83 EKE Added code to quit if sys called on a drive across
  20. ; a net.
  21. ; 1.84 09/09/83 CHRISP grabbed against his will to make this stupid
  22. ; program write out a boot sector
  23. ; 1.85 10/18/83 NP Printf to print messages and it's now an .EXE file
  24. ; 1.86 11/8/83 MZ fix hard file output of boot sector
  25. ; 1.87 5/1/84 MZ make sys prompt for system disk in default drive.
  26. ; 3.20 11/9/84 RS make sys write out a correct boot sector for the
  27. ; version of DOS. It grabs the boot sector off the system
  28. ; disk and inserts the correct BPB.
  29. ; Uses IOCTL Get Device Parms to get BPB for a Hard drive.
  30. ; 3.20 08/5/85 RS Allow FAT ID byte of 0F0H for 'strange' media
  31. ; layouts. These come about because of /T /N switches in
  32. ; FORMAT.
  33. ; 3.20 09/16/85 Incorporate tables of filenames to allow system files
  34. ; used by other OEMs to be SYSed onto disks formatted on
  35. ; other MSDOS systems. Allows the flexibility to replace
  36. ; system files for one OEM by system files for another.
  37. ;
  38. ;
  39. ; 3.30 06/04/86 MT removes initial check for IBMBIO and DOS - not needed
  40. ; because of later search of dirs
  41. ; 3.30 06/16/86 MT only force part of IBMBIO contig - do this by assuming
  42. ; contig part smaller than 1.10 BIOS
  43. ; 3.30 06/16/86 MT Check diks space for enough room to install BIO and DOS
  44. .xlist
  45. .xcref
  46. include version.inc
  47. INCLUDE DOSSYM.INC ;also defines version of dos
  48. include ioctl.INC
  49. .cref
  50. .list
  51. ;IBMJAPVER EQU FALSE ; this and the following are mutually
  52. ;IBMVER EQU TRUE ; exclusive
  53. ;IBMCOPYRIGHT EQU FALSE
  54. printf_code segment public
  55. extrn printf:far
  56. printf_code ends
  57. CODE SEGMENT PARA PUBLIC
  58. CODE ENDS
  59. CONST SEGMENT BYTE PUBLIC
  60. EXTRN BIOSNamesTable:byte, DOSNamesTable:byte
  61. EXTRN SourceBIOSFile:byte, SourceDOSFile:byte
  62. CONST ENDS
  63. cstack segment stack
  64. db 278 + 80h dup (?) ; 278 == IBM's ROM requirements
  65. cstack ends
  66. DATA SEGMENT BYTE PUBLIC
  67. DG GROUP CODE,DATA,CONST,cstack
  68. EXTRN BADDRV_ptr:byte, BADPARM_ptr:byte, GETSYS_ptr:byte
  69. EXTRN SYSDRV:byte, NODEST_ptr:byte, BADSIZ_ptr:byte, DONE_ptr:byte
  70. EXTRN BADVER:byte, Crlf_ptr:byte, NoSYS_PTR:byte, GetTarg_ptr:byte
  71. EXTRN TargDrv:byte
  72. EXTRN NotNetM_ptr:byte
  73. DEFALT DB 0
  74. IF IBMCOPYRIGHT
  75. BIOSName DB "A:\IBMBIO.COM",0
  76. DOSName DB "A:\IBMDOS.COM",0
  77. SourceBIOSName DB "A:\IBMBIO.COM",0
  78. SourceDOSName DB "A:\IBMDOS.COM",0
  79. ELSE
  80. BIOSName DB "A:\IO.SYS",0
  81. DOSName DB "A:\MSDOS.SYS",0
  82. SourceBIOSName DB "A:\IO.SYS",0
  83. SourceDOSName DB "A:\MSDOS.SYS",0
  84. ENDIF
  85. IBMBIO_LOW DW 0 ;length of IBMBIO on disk
  86. IBMBIO_HIGH DW 0
  87. IBMDOS_LOW DW 0 ;length of old IBMDOS on disk
  88. IBMDOS_HIGH DW 0
  89. SIZE_OLD_HIGH DW 0
  90. SIZE_OLD_LOW DW 0
  91. NEWBIO_SIZE_LOW DW 0
  92. NEWBIO_SIZE_HIGH DW 0
  93. NEWDOS_SIZE_LOW DW 0
  94. NEWDOS_SIZE_HIGH DW 0
  95. Need_Clusters dw 0
  96. Bytes_Per_Cluster dw 0
  97. Number_Free_Clusters dw 0
  98. ;*** WARNING ***
  99. ; KEEP THE FOLLOWING ITEMS IN THE EXACT ORDER BELOW!!!
  100. DOSEntFree DB 1
  101. BIOSEntFree DB 1
  102. BIOSInFH DW ? ; file handle of source BIOS
  103. BIOSLenLow DW 2 DUP (?) ; 32-bit length of BIOS
  104. BIOSLenHigh DW 2 DUP (?) ; 32-bit length of BIOS
  105. BIOSTime DW 2 DUP (?) ; place to store time of BIOS write
  106. BIOSOutFH DW ? ; fh of BIOS destination
  107. DOSInFH DW ? ; file handle of source DOS
  108. DOSLenLow DW 2 DUP (?) ; 32-bit length of DOS
  109. DOSLenHigh DW 2 DUP (?) ; 32-bit length of DOS
  110. DOSTime DW 2 DUP (?) ; place to store time of DOS write
  111. DOSOutFH DW ? ; fh of DOS destination
  112. AllName DB "A:\*.*",0
  113. ;******************************************
  114. ;FCB SNOT
  115. fcb_copy db 32 dup(?)
  116. IF IBMCOPYRIGHT
  117. FCBDOS DB "IBMDOS COM"
  118. FCBBIO DB "IBMBIO COM"
  119. ELSE
  120. FCBDOS DB "MSDOS SYS"
  121. FCBBIO DB "IO SYS"
  122. ENDIF
  123. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  124. DOSFile_Offset dw 0 ; Index for system file names in Tables
  125. DirEnt DB 80h DUP (?)
  126. cbBuf DW ? ; number of bytes in buffer
  127. pDOS DW ? ; offset of beginning of DOS in buffer
  128. pDOSEnd DW ? ; offset of end of DOS in buffer
  129. BIOSEG EQU 70H ; STARTING LOCATION OF BIOS
  130. BPBLEN EQU 19
  131. BPB LABEL DWORD ; POINTER TO HARDFILE BPB
  132. DW 0000
  133. DW BIOSEG
  134. public boot
  135. BOOT DB 0,0,0 ; SKIP THE THREE BYTE JUMP
  136. DB "MSDOS3.3"
  137. SECSIZ DW 512 ; SECTOR SIZE
  138. SECALL DB 1 ; SECTOS PER ALLOCATION UNIT
  139. RESNUM DW 1 ; RESERVED SECTORS
  140. FATNUM DB 2 ; NUMBER OF FATS
  141. DIRNUM DW 64 ; NUMBER OF DIRECTORY ENTRIES
  142. SECNUM DW 1*8*40 ; NUMBER OF SECTORS
  143. FATID DB 0FEH
  144. FATSIZE DW 1
  145. SECLIM DW 8
  146. HDLIM DW 1
  147. HIDDEN DW 0
  148. PHYDRV DB 0
  149. DB 510-($-boot) dup (?)
  150. DB 55H,0AAH ; MAGIC WORD
  151. REORG LABEL BYTE
  152. ORG BOOT
  153. INCLUDE ..\BOOT\BOOT.INC
  154. ORG REORG
  155. FATID_TABLE LABEL WORD
  156. DW 0 ; F8 FIXED DISK
  157. DW -2 ; F9
  158. DW -1 ; FA
  159. DW -1 ; FB
  160. DW OFFSET DG:BPB91 ; FC
  161. DW OFFSET DG:BPB92 ; FD
  162. DW OFFSET DG:BPB81 ; FE
  163. DW OFFSET DG:BPB82 ; FF
  164. ; BIOS PARAMETER BLOCKS FOR THE VARIOUS MEDIA
  165. BPB81 DB 1
  166. DW 1
  167. DB 2
  168. DW 64
  169. DW 1*8*40
  170. DB 0FEH
  171. DW 1
  172. DW 8
  173. DW 1
  174. DW 0
  175. DB 0
  176. BPB82 DB 2
  177. DW 1
  178. DB 2
  179. DW 112
  180. DW 2*8*40
  181. DB 0FFH
  182. DW 1
  183. DW 8
  184. DW 2
  185. DW 0
  186. DB 0
  187. BPB91 DB 1
  188. DW 1
  189. DB 2
  190. DW 64
  191. DW 1*9*40
  192. DB 0FCH
  193. DW 2
  194. DW 9
  195. DW 1
  196. DW 0
  197. DB 0
  198. BPB92 DB 2
  199. DW 1
  200. DB 2
  201. DW 112
  202. DW 2*9*40
  203. DB 0FDH
  204. DW 2
  205. DW 9
  206. DW 2
  207. DW 0
  208. DB 0
  209. BPB96T DB 1 ; mjb001
  210. DW 1
  211. DB 2
  212. DW 224
  213. DW 2*15*80
  214. DB 0f9H
  215. DW 7
  216. DW 15
  217. DW 2
  218. DW 0
  219. DB 0
  220. BPBSIZ = $-BPB96T
  221. BPB325 DB 2 ; mjb001
  222. DW 1
  223. DB 2
  224. DW 70h
  225. cSec325 DW 2*9*80
  226. DB 0f9H
  227. DW 3
  228. DW 9
  229. DW 2
  230. DW 0
  231. DB 0
  232. ;
  233. ; Following structure used by Generic IOCTL call Get Device Parameters to get
  234. ; the BPB of a hard disk. It 'overflows' into area of BUF.
  235. ;
  236. DeviceParameters a_DeviceParameters <0,DEV_HARDDISK>
  237. BUF LABEL BYTE ; beginning of area for file reads
  238. DATA ENDS
  239. CODE SEGMENT PUBLIC PARA
  240. ASSUME CS:DG,DS:NOTHING,ES:NOTHING,SS:CSTACK
  241. start:
  242. JMP SHORT CheckVersion
  243. DW OFFSET DG:BOOT
  244. HEADER DB "SYS 3.30"
  245. CheckVersion:
  246. PUSH AX ; save drive letter validity
  247. MOV AH,GET_VERSION
  248. INT 21H ; get dos version
  249. cmp ax,expected_version
  250. jne gotbaddos
  251. ; XCHG AH,AL ; Turn it around to AH.AL
  252. ; CMP AX,DOSVER_LOW ; is it too low?
  253. ; JNE GOTBADDOS ; yes, error
  254. pop ax
  255. ASSUME DS:NOTHING,ES:NOTHING
  256. push cs
  257. pop es
  258. ASSUME ES:DG
  259. mov si,5ch
  260. mov di,offset dg:fcb_copy
  261. mov cx,32
  262. rep movsb
  263. push cs
  264. pop ds
  265. ASSUME DS:DG
  266. MOV DX,OFFSET DG:DirEnt
  267. MOV AH,SET_DMA
  268. INT 21h
  269. jmp sys
  270. GOTBADDOS:
  271. push cs
  272. pop ds
  273. ASSUME DS:DG
  274. MOV DX,OFFSET DG:BADVER ; message to dump
  275. mov ah,std_con_string_output
  276. int 21h
  277. push es
  278. xor ax,ax
  279. push ax
  280. foo proc far
  281. ret ; Must use this method, version may be < 2.00
  282. foo endp
  283. ERR0:
  284. ASSUME DS:DG,ES:DG
  285. MOV DX,OFFSET DG:BADPARM_ptr ; no drive letter
  286. JMP xerror
  287. ERR1:
  288. ASSUME DS:DG,ES:DG
  289. MOV DX,OFFSET DG:BADDRV_ptr ; drive letter invalid
  290. JMP xerror
  291. ;
  292. ; We do not have a disk that has an available system in the root. See if the
  293. ; media is removable and if so, ask the user for a replacement. If the media
  294. ; is not removable, then die gracefully.
  295. ;
  296. ERR2:
  297. ASSUME DS:DG,ES:DG
  298. MOV AH,GET_DEFAULT_DRIVE ;Will find out the default drive
  299. INT 21H ;Default now in AL
  300. MOV BL,AL
  301. INC BL ; A = 1
  302. Call IsRemovable
  303. jnc DoPrompt
  304. MOV DX,OFFSET DG:NoSys_PTR
  305. PUSH DX
  306. CALL PRINTF
  307. MOV AX,4C01h
  308. INT 21h
  309. DoPrompt:
  310. MOV AL,DEFALT ; get default drive number
  311. ADD AL,'A'-1 ; turn into letter
  312. MOV SYSDRV,AL
  313. MOV DX,OFFSET DG:GETSYS_ptr
  314. push dx
  315. call printf
  316. CALL GetKeystroke ; wait for him to type simething
  317. XOR AL,AL ; valid drive spec now...
  318. SYS:
  319. ASSUME DS:DG,ES:DG
  320. mov DOSEntFree,1
  321. mov BIOSEntFree,1
  322. CMP BYTE PTR fcb_copy+1," " ; Was file specified?
  323. JNZ ERR0 ; yes, no files are allowed -> error
  324. CMP AL,-1 ; Invalid drive spec?
  325. JZ ERR1 ; yes, must have valid drive -> error
  326. CMP BYTE PTR fcb_copy,0 ; No drive specified?
  327. JZ ERR1 ; yes, cannot sys to default drive error
  328. MOV AH,GET_DEFAULT_DRIVE ; Get default drive
  329. INT 21H
  330. INC AL ; turn from phys drive to logical drive
  331. MOV DEFALT,AL ; save it for possible printing
  332. CMP BYTE PTR fcb_copy,AL ; did he specify the default drive?
  333. JZ ERR1 ; yes, default drive not allowed
  334. ;------Code to quit if sys called on a drive across a net-----------------------
  335. CheckNet:
  336. MOV BL,BYTE PTR fcb_copy ; x = IOCTL (getdrive, Drive+1);
  337. MOV AX,(IOCTL SHL 8) + 9
  338. INT 21H
  339. JC NotNet
  340. TEST DX,1200H ; if(x & 0x1000)(redirected or shared)
  341. JZ NotNet
  342. MOV DX,OFFSET DG:NotNetM_ptr ; Fatal ("Can't do over net");
  343. JMP xerror
  344. ;-------Load up BIOS and DOS at this point ---------------------------------
  345. NotNet:
  346. MOV AL,DEFALT
  347. ADD AL,'A'-1 ; turn into letter
  348. MOV SourceBIOSName,AL ; twiddle source name
  349. MOV SourceDOSName,AL ; twiddle source name
  350. CLD
  351. MOV DX,OFFSET DG:SourceBIOSName ; source name
  352. MOV CX,7
  353. MOV AH,4Eh
  354. INT 21h
  355. JC ERR2J
  356. MOV AX,WORD PTR DG:DIRENt+26
  357. MOV WORD PTR NEWBIO_SIZE_LOW,AX
  358. MOV AX,WORD PTR DG:DIRENt+28
  359. MOV WORD PTR NEWBIO_SIZE_HIGH,AX
  360. MOV DX,OFFSET DG:SourceBIOSName ; source name
  361. MOV DI,OFFSET DG:BIOSInFH ; pointer to block of data
  362. CALL OpenFile
  363. JNC NotERR2
  364. ERR2J:
  365. JMP Err2 ; not found, go and try again
  366. NotERR2:
  367. MOV DX,OFFSET DG:SourceDOSName ; source name
  368. MOV CX,7
  369. MOV AH,4Eh
  370. INT 21h
  371. JC ERR2J
  372. MOV AX,WORD PTR DG:DIRENt+26
  373. MOV WORD PTR NEWDOS_SIZE_LOW,AX
  374. MOV AX,WORD PTR DG:DIRENt+28
  375. MOV WORD PTR NEWDOS_SIZE_HIGH,AX
  376. MOV DX,OFFSET DG:SourceDOSName ; source of DOS
  377. MOV DI,OFFSET DG:DOSInFH ; pointer to block of data
  378. CALL OpenFile ; Look for DOS
  379. JC ERR2J ; not there, go ask for a system disk
  380. MOV CX,SP ; get lowest available spot
  381. SUB CX,0200h+(OFFSET DG:BUF); leave room for all sorts of things
  382. MOV cbBuf,CX ; store length away
  383. CALL FillMem ; load up memory with files
  384. JC ERR2J ; Some kind of error reading system
  385. CheckDest:
  386. ;------------Check for "valid" destination-----------------------------------
  387. MOV AH,0Dh
  388. INT 21h
  389. MOV AL,BYTE PTR fcb_copy
  390. DEC AL
  391. MOV BX,OFFSET DG:buf ; Temp space
  392. MOV DX,1 ; Sector 1 (first sec of FAT)
  393. MOV CX,DX ; One sector
  394. INT 25H ; Read Fat sector
  395. POP AX ; Flags
  396. JC PromptDest ; Issue prompt to insert Destination
  397. ; disk
  398. CMP BYTE PTR [BUF],0F8H
  399. JAE OKFAT
  400. ;---------Treat 0F0H as a valid 'IBM' FAT ID byte--------------------------------
  401. cmp BYTE PTR [BUF],0F0H
  402. je OKFAT
  403. JMP ERR3
  404. PromptDest:
  405. push ax
  406. mov al,Byte ptr fcb_copy ; Get destination ID
  407. ADD AL,'A'-1 ; turn into letter
  408. MOV TargDrv,AL
  409. MOV DX,OFFSET DG:GetTarg_ptr
  410. push dx
  411. call printf
  412. CALL GetKeystroke ; wait for him to type simething
  413. pop ax
  414. jmp CheckDest
  415. ;-------The Fat appears to be OK... See if DOS/Bios there-----------------
  416. OKFAT:
  417. ;
  418. ;Set up drive letter in destignation filespecs
  419. ;
  420. MOV AL,BYTE PTR fcb_copy
  421. ADD AL,'A'-1 ; convert to letter
  422. MOV BIOSName,AL ; point names at destination drive
  423. MOV DOSName,AL
  424. ;
  425. ; Read in first sector of directory
  426. ;
  427. ; The reason that we do the direct read of the directory is the find first/next
  428. ; or search first/next do an exclusive search for volume labels. By using these
  429. ; calls, there is no way to determine if a volume label occupies the first
  430. ; location in the directory. Hence we get sleazy and read the directory directly
  431. ; (no pun intended) to get this info. While its in there, go ahead and grab the file
  432. ; sizes. -MT
  433. ;
  434. GetDir:
  435. MOV DL,Byte PTR fcb_copy
  436. MOV AH,Get_DPB
  437. PUSH DS
  438. INT 21h
  439. ; DS:BX point to DPB
  440. MOV DX,[BX.dpb_dir_sector]
  441. POP DS
  442. MOV AL,BYTE PTR fcb_copy
  443. DEC AL
  444. MOV BX,OFFSET DG:BUF ; Temp space
  445. MOV CX,1 ; Sector 1 (first sec of FAT)
  446. INT 25H ; Read Fat sector
  447. POP AX ; Flags
  448. JNC Skip
  449. ;
  450. ;NOTE!!!! This next jump is actually a bug left over from the MS days - if the
  451. ;dir is not read successfully then the SYS should be canned at that point -
  452. ;however, up thru 3.20 this would just jump to the actual sys. To make things
  453. ; a little better I jump to an error - this needs to be DCR'd for a real error
  454. ;
  455. JMP Err3
  456. Skip:
  457. ;
  458. ; Now see if the first two directory entries are available... First check
  459. ; for being free:
  460. ;
  461. MOV SI,OFFSET DG:BUF
  462. CMP BYTE PTR [SI],0 ; empty dir?
  463. JE Get_Space ; yes, go check for conflicts
  464. CLD
  465. CMP BYTE PTR [SI],0E5h
  466. JE SecondFree
  467. ;
  468. ; The first entry is not free. See if the BIOS is there
  469. ;
  470. MOV DI,OFFSET DG:FCBBIO
  471. MOV CX,11
  472. REP CMPSB
  473. JNE Err3jj ; not BIOS
  474. DEC BIOSEntFree
  475. ; added by dcl 8/24/86 - most cases solution
  476. mov ax,0002 ; is ibmbio allocated the 1st cluster?
  477. cmp ax,word ptr DG:BUF+26 ; that being cluster 2???
  478. JNE Err3jj ; not cluster 2 - error; go display
  479. ; end added by dcl 8/24/86
  480. ;
  481. ; IBM change - MT 6/16/86
  482. ; Get the size of the file for IBMBIO
  483. ;
  484. MOV ax,word ptr DG:BUF+28
  485. MOV word ptr IBMBIO_Low,ax
  486. MOV ax,word ptr DG:BUF+30
  487. MOV word ptr IBMBIO_High,ax
  488. ; Check the second entry
  489. ;
  490. SecondFree:
  491. MOV SI,OFFSET DG:BUF+32
  492. CMP BYTE PTR [SI],0 ; empty dir?
  493. JE Get_Space ; yes, go check for conflicts
  494. CMP BYTE PTR [SI],0E5h ; how about second?
  495. JE Get_Space
  496. ;
  497. ; This entry is not free. Check it for IBMDOS
  498. ;
  499. MOV DI,OFFSET DG:FCBDOS
  500. MOV CX,11
  501. REP CMPSB
  502. Err3jj: JNZ Err3j1 ; not DOS
  503. DEC DOSEntFree
  504. ;
  505. ; IBM change - MT 6/16/86
  506. ; Get the file size for IBMDOS
  507. ;
  508. MOV ax,word ptr DG:BUF+60
  509. MOV word ptr IBMDOS_Low,ax
  510. MOV ax,word ptr DG:BUF+62
  511. MOV word ptr IBMDOS_High,ax
  512. ;
  513. ; We now have the following:
  514. ; Whether or not there is a DOS/BIOS on the disk
  515. ; Whether or not the appropriate entry is free
  516. ; We are guaranteed that if the entry is free, then it has the correct file in
  517. ;
  518. ;IBM CHANGE - MT 6/16/86
  519. ;
  520. ; Here we make some VERY IMPORTANT assumptions.
  521. ;
  522. ;1) If IBMBIO exists on the disk currently, we assume it is in the correct
  523. ; place, i.e. at the front of the data area and contiguous.
  524. ;2) The stub loader portion of IBMBIO is less than 2048 bytes long. This
  525. ; number comes about by assuming we will never overlay anything smaller
  526. ; than 1920 bytes (DOS 1.10 IBMBIO size). This can be expanded to 2048 if
  527. ; we also assume the smallest possible cluster length is 512 bytes.
  528. ;
  529. ; Therefore, if we have an empty disk or IBMBIO exists, then we have enough
  530. ; contiguous room to install the portion of IBMBIO that requires itself to
  531. ; be contiguous.
  532. ;
  533. ;IBM CHANGE - MT 6/16/86
  534. ;
  535. ;See if enough free space for IBMBIO and IBMDOS
  536. ;
  537. GET_SPACE:
  538. MOV AH,36H ;Get free space
  539. MOV DL,byte ptr fcb_copy ;Get the drive letter
  540. INT 21h
  541. ;16 bit math okay here, no danger of overflow
  542. MUL CX ;Get bytes/cluster
  543. ;Result left in AX
  544. PUSH AX ;Save it for later
  545. MOV Bytes_Per_Cluster,AX
  546. MOV Number_Free_Clusters,BX
  547. ;Low result in AX, High result in DX
  548. ;Get IBMBIO size
  549. MOV AX,IBMBIO_Low
  550. MOV DX,IBMBIO_High
  551. CALL Get_Clusters
  552. ADD Number_Free_Clusters,AX
  553. ;Low result in AX, High result in DX
  554. ;Get IBMDOS size
  555. MOV AX,IBMDOS_Low
  556. MOV DX,IBMDOS_High
  557. CALL Get_Clusters
  558. ADD Number_Free_Clusters,AX
  559. ;Find the total size of new DOS and BIOS
  560. MOV AX,NEWBIO_Size_Low
  561. MOV DX,NEWBIO_Size_High
  562. CALL Get_Clusters
  563. Got_NEW_BIO_Clusters:
  564. MOV Need_Clusters,AX
  565. MOV AX,NEWDOS_Size_Low
  566. MOV DX,NEWDOS_Size_High
  567. CALL Get_Clusters
  568. ADD AX,Need_Clusters
  569. ;Now see if there is enough room for all of it on the disk
  570. CMP AX,Number_Free_Clusters
  571. JBE PUT_SYS
  572. ERR3J1:
  573. JMP ERR3
  574. ;Go do the sys
  575. PUT_SYS:
  576. CMP BIOSEntFree,0
  577. JNE GetRidDOS
  578. MOV DX,OFFSET DG:BIOSName ; who to change mode
  579. MOV CX,0 ; undo attributes
  580. MOV AX,(ChMod SHL 8) + 1 ; set the attributes
  581. INT 21h
  582. MOV DX,OFFSET DG:BIOSName
  583. MOV AX,(UNLINK SHL 8)
  584. INT 21H ; Delete BIOS file
  585. GetRidDOS:
  586. CMP DOSEntFree,0
  587. JNE CreateBIOS
  588. MOV DX,OFFSET DG:DOSName ; who to change mode
  589. MOV CX,0 ; undo attributes
  590. MOV AX,(ChMod SHL 8) + 1 ; set the attributes
  591. INT 21h
  592. MOV DX,OFFSET DG:DOSName
  593. MOV AX,(UNLINK SHL 8)
  594. INT 21H ; Delete DOS file
  595. CreateBIOS:
  596. MOV DX,OFFSET DG:BIOSName ; destination of BIOS
  597. MOV CX,7 ; fancy attributes
  598. MOV AH,Creat ; make a new one
  599. INT 21h
  600. JC err3j2
  601. MOV BIOSOutFH,AX ; save handle
  602. MOV DX,OFFSET DG:DOSName ; destination of DOS
  603. MOV AH,Creat ; make a new one
  604. INT 21h
  605. JC err3j2
  606. MOV DOSOutFH,AX ; save handle
  607. PUSH DS
  608. MOV AH,GET_DPB
  609. MOV DL,BYTE PTR fcb_copy ; Target drive
  610. INT 21H
  611. MOV [BX.dpb_next_free],0 ; Reset Allocation to start of disk
  612. ; so BIOS goes in right place!
  613. POP DS
  614. Copy:
  615. CALL DumpMem ; flush out memory
  616. JC ERR3J2 ; Disk full or some other error
  617. MOV AX,DOSLenHigh ; more DOS?
  618. OR AX,DOSLenLow ; more low dos
  619. OR AX,BIOSLenHigh ; more high BIOS
  620. OR AX,BIOSLenLow ; more low BIOS
  621. JZ AllDone ; nope, all done
  622. CALL FillMem ; reload world
  623. JNC Copy
  624. JMP ERR2 ; Start over again
  625. ERR3J2:
  626. JMP ERR3
  627. ERR4:
  628. MOV DX,OFFSET DG:BADSIZ_ptr
  629. JMP xerror
  630. AllDone:
  631. MOV CX,BIOSTime ; get time and date
  632. MOV DX,BIOSTime+2
  633. MOV BX,BIOSOutFH ; where to stuff the time
  634. MOV AX,(File_Times SHL 8) + 1
  635. INT 21h
  636. MOV AH,Close
  637. INT 21h
  638. MOV CX,DOSTime ; get time and date
  639. MOV DX,DOSTime+2
  640. MOV BX,DOSOutFH ; where to stuff the time
  641. MOV AX,(File_Times SHL 8) + 1
  642. INT 21h
  643. MOV AH,Close
  644. INT 21h
  645. CALL PUTBOOT ; copy the boot sector also
  646. MOV DX,OFFSET DG:DONE_ptr ; all finished message
  647. push dx
  648. call printf
  649. XOR AL,AL ; ok error code
  650. jmp short rexit
  651. xerror:
  652. push dx
  653. call printf
  654. mov dx,offset dg:crlf_ptr
  655. push dx
  656. call printf
  657. mov al,0ffh
  658. rexit:
  659. MOV AH,EXIT ; bye and return error code
  660. INT 21h
  661. POPRET:
  662. POP CX
  663. SETERR:
  664. STC
  665. return
  666. Get_Clusters:
  667. ;Round up to the next cluster size
  668. MOV BX,Bytes_Per_Cluster ;Bytes/cluster
  669. DIV BX ;If there is a remainder in DX, then
  670. ;we have another cluster to round up
  671. CMP DX,0
  672. JE Got_CLUSTERS
  673. INC AX ;Round up to next cluster
  674. Got_Clusters:
  675. RET
  676. FillMem:
  677. MOV CX,cbBuf ; get length of buffer
  678. MOV BX,BIOSInFH ; get bios source handle
  679. MOV DX,OFFSET DG:BUF+512 ; point to beginning of buffer
  680. ; past area to read in boot rec
  681. PUSH CX ; save away total length
  682. CMP BIOSLenHigh,0 ; > 64K to read?
  683. JA UseCX ; use CX
  684. CMP BIOSLenLow,CX ; more left to read?
  685. JA UseCX ; use CX
  686. MOV CX,BIOSLenLow ; move new
  687. UseCX:
  688. MOV AH,Read
  689. INT 21h ; read in what we can
  690. JC POPRET ; Error
  691. CMP AX,CX ; Did we get it all?
  692. JNZ POPRET ; No, error
  693. ADD DX,AX ; update pointer for DOS Read
  694. MOV pDOS,DX ; point to beginning of DOS
  695. SUB BIOSLenLow,AX ; decrement remaining
  696. SBB BIOSLenHigh,0 ; do 32 bit
  697. POP CX ; get original length
  698. SUB CX,AX ; this much is left
  699. MOV BX,DOSInFH ; get bios source handle
  700. CMP DOSLenHigh,0 ; > 64K to read?
  701. JA UseCXDOS ; use CX
  702. CMP DOSLenLow,CX ; more left to read?
  703. JA UseCXDOS ; use CX
  704. MOV CX,DOSLenLow ; move new
  705. UseCXDOS:
  706. MOV AH,Read
  707. INT 21h ; read in what we can
  708. retc ; error
  709. CMP AX,CX
  710. JNZ SETERR ; Didn't read it all
  711. ADD DX,AX ; update pointer for DOS Read
  712. MOV pDOSEnd,DX ; point to End of dos DOS
  713. SUB DOSLenLow,AX ; decrement remaining
  714. SBB DOSLenHigh,0 ; do 32 bit arithmetic
  715. CLC
  716. return
  717. OpenFile:
  718. MOV AX,(OPEN SHL 8) + 0 ; open for reading only
  719. INT 21H ; Look for BIOS
  720. retc ; not found, go and try again
  721. STOSW ; stash away handle
  722. MOV BX,AX ; get ready for seeks
  723. MOV AX,(LSeek SHL 8) + 2 ; seek relative to eof
  724. XOR CX,CX ; zero offset
  725. XOR DX,DX ; zero offset
  726. INT 21h ; get offsets
  727. STOSW ; save low part of size
  728. STOSW ; save low part of size
  729. MOV AX,DX
  730. STOSW ; save high part of size
  731. STOSW ; save high part of size
  732. XOR DX,DX ; zero offset
  733. MOV AX,(LSeek SHL 8) + 0 ; seek relative to beginning
  734. INT 21h
  735. MOV AX,(File_Times SHL 8) + 0
  736. INT 21h ; get last write times
  737. MOV AX,CX
  738. STOSW ; save time
  739. MOV AX,DX
  740. STOSW ; save date
  741. return
  742. ERR3:
  743. MOV DX,OFFSET DG:NODEST_ptr
  744. JMP xerror
  745. DumpMem:
  746. MOV DX,OFFSET DG:BUF+512 ; get offset of bios start
  747. MOV CX,pDOS ; beginning of next guy
  748. SUB CX,DX ; difference is length
  749. JZ DumpDos ; no bios to move
  750. MOV BX,BIOSOutFH ; where to output
  751. MOV AH,Write
  752. INT 21h ; wham
  753. retc ; error
  754. CMP AX,CX ; Did it work?
  755. JNZ WRERR ; No
  756. DumpDos:
  757. MOV DX,pDOS ; beginning of dos
  758. MOV CX,pDOSEnd ; end of dos
  759. SUB CX,DX ; difference is length
  760. retz ; if zero no write
  761. MOV BX,DOSOutFH ; where to output
  762. MOV AH,Write
  763. INT 21h ; wham
  764. retc ; error
  765. CMP AX,CX ; Did it work?
  766. retz ; Yes, carry clear
  767. WRERR:
  768. STC
  769. return
  770. ;
  771. ; Output a boot sector apporpriate to the supposed version of DOS. We do this
  772. ; by reading in the boot sector for the drive and getting the BPB from there.
  773. ; This works fine until we get a 1.x diskette, when we have to grab the media
  774. ; descriptor byte and select the correct BPB using that.
  775. ;
  776. public putboot
  777. PUTBOOT:
  778. mov ax,dg ; initialize DS.
  779. mov ds,ax
  780. mov al,byte ptr fcb_copy ; target drive 1-based
  781. dec al ; convert to 0-based
  782. mov dx,0000H ; get relative sector 0
  783. call Read_Sec
  784. jc Do_Media_Byte
  785. cmp word ptr DG:[Buf+1FEH], 0AA55H ; Is it a 1.x disk?
  786. jnz Do_Media_Byte
  787. PB0:
  788. mov si,(offset DG:Buf)+13 ; Set up SI to point to 'SECALL' in
  789. ; the BPB just read in.
  790. jmp PB7
  791. ;
  792. ; We were unable to use the BPB in the boot sector, so we must now get a
  793. ; valid BPB by examining the media descriptor byte.
  794. ;
  795. Do_Media_Byte:
  796. MOV AH,GET_DPB
  797. MOV DL,BYTE PTR fcb_copy ; Target drive
  798. INT 21H
  799. MOV AL,[BX.dpb_media] ; Media byte
  800. PUSH CS
  801. POP DS
  802. SUB AL,0F8H
  803. CBW
  804. MOV BX,AX ; BX has offset into bpb table
  805. SHL BX,1 ; Word table, mult by 2
  806. MOV SI,[BX+FATID_TABLE] ; get pointer to bpb
  807. OR SI,SI ; hardfile?
  808. JNZ PB3 ; nope.
  809. ;
  810. ; We have a hard drive. We can use the IOCTL Get Device Parameters to get the
  811. ; BPB for the hard drive.
  812. ;
  813. mov bl,byte ptr fcb_copy ; Drive number
  814. mov dx,offset DeviceParameters
  815. mov ah,IOCTL
  816. mov al,GENERIC_IOCTL
  817. mov ch,RAWIO
  818. mov cl,Get_Device_Parameters
  819. int 21H
  820. mov bx,dx ; ds:bx-> DeviceParameters
  821. lea si,byte ptr [bx].DP_BPB ; SI -> BPB returned
  822. inc si
  823. inc si ; si-> secall in BPB
  824. PB3: CMP SI,-1 ; weird internal error?
  825. JZ PB9
  826. CMP SI,-2 ; new multi-value FAT ID?
  827. JNZ PB7 ; nope.
  828. ;
  829. ; We may have a FAT ID of F9. This may represent TWO different media in two
  830. ; incompatible drives. We do a get free space to determine which.
  831. ;
  832. MOV AH,Get_Drive_freespace
  833. MOV DL,BYTE PTR FCB_copy
  834. INT 21h
  835. MOV BX,DX
  836. MUL BX ; compute total sectors
  837. CMP AX,cSec325
  838. MOV SI,OFFSET DG:BPB325
  839. JB PB7
  840. MOV SI,OFFSET DG:BPB96T
  841. PB7: PUSH DS ; COPY IN THE NEW STUFF
  842. POP ES
  843. MOV DI,OFFSET DG:SECALL
  844. MOV CX,BPBSIZ
  845. CLD
  846. REP MOVSB
  847. PB8:
  848. cmp dg:FATID,0F8H ; Hard drive?
  849. jnz not_hard
  850. ; NOTE:
  851. ; The physical hard drive number is placed in the third byte from the end in the
  852. ; boot sector in DOS 3.2. This is a change from the previous DOS versions.
  853. ;
  854. mov byte ptr dg:[boot+1FDH],80H ; set physical hard drive number
  855. not_hard:
  856. MOV AL,BYTE PTR fcb_copy
  857. DEC AL
  858. MOV BX,OFFSET DG:BOOT ; Boot sector
  859. XOR DX,DX ; Sector 0
  860. MOV CX,DX
  861. INC CX ; One sector
  862. INT 26H ; Write out 8 sector boot sector
  863. jnc pb9
  864. PB9: POP AX ; Flags
  865. RET
  866. ;
  867. ; Read_Sec reads the sector and track specified in DX from the drive in AL.
  868. ; The sector is read into location Buf. Carry set if error.
  869. ;
  870. READ_SEC:
  871. push ax ; save registers
  872. mov cx,0001H
  873. mov bx,Offset DG:Buf ; temp. buffer
  874. int 25H
  875. pop ax ; Pop flags pushed by Int 25
  876. Read_Ret:
  877. pop ax
  878. ret
  879. GetKeystroke:
  880. MOV AX,(Std_CON_Input_Flush SHL 8) + Std_CON_Input_No_Echo
  881. INT 21H
  882. MOV AX,(Std_CON_Input_Flush SHL 8) + 0
  883. INT 21H
  884. mov dx,offset dg:crlf_ptr
  885. push dx
  886. call printf
  887. return
  888. ;
  889. ; Determine if the drive indicated in BX is removable or not.
  890. ;
  891. ; Inputs: BX has drive (0=default, 1=A)
  892. ; Outputs: Carry clear => removable
  893. ; Carry set => non-removable
  894. ;
  895. ; Registers modified: none
  896. ;
  897. IsRemovable:
  898. SaveReg <AX>
  899. mov AX,(IOCTL SHL 8) OR 8 ; do a media check
  900. INT 21H
  901. jnc CheckRemove
  902. MOV AX,(IOCTL SHL 8) OR 9 ; Is it a net drive
  903. INT 21H
  904. jc NotRemove ; Yipe! Say non-removable
  905. TEST DX,1000H
  906. jnz NotRemove ; Is NET drive. Say non-removable.
  907. JMP IsRemove
  908. CheckRemove:
  909. TEST ax,1
  910. jnz NotRemove
  911. IsRemove:
  912. CLC
  913. RestoreReg <AX>
  914. return
  915. NotRemove:
  916. STC
  917. RestoreReg <AX>
  918. return
  919. ;
  920. ; Moves the name at the current locations in the system file name tables into
  921. ; the relevant system variables for later use.
  922. ; Preserves all registers (except flags).
  923. ;
  924. MoveNames:
  925. push bx
  926. push cx
  927. push di
  928. push si
  929. cld
  930. mov bx,word ptr DOSFile_Offset
  931. mov si,offset DG:BIOSNamesTable
  932. add si,bx
  933. mov di,offset DG:BIOSName
  934. add di,3 ; skip over drive,colon,back-slash
  935. mov cx,11
  936. repe movsb
  937. mov si,offset DG:DOSNamesTable
  938. add si,bx
  939. mov di,offset DG:DOSName
  940. add di,3 ; skip over drive,colon,back-slash
  941. mov cx,11
  942. repe movsb
  943. pop si
  944. pop di
  945. pop cx
  946. pop bx
  947. ret
  948. ;
  949. ; Set up filename in FCB variables for searching directory entries.
  950. ;
  951. SetUpFCB:
  952. push si
  953. push di
  954. push bx
  955. mov si,offset DG:BIOSNamesTable
  956. mov bx,word ptr DOSFile_Offset
  957. add si,bx
  958. mov di,offset DG:FCBBIO
  959. call MoveToFCB
  960. mov si,offset DG:DOSNamesTable
  961. mov bx,word ptr DOSFile_Offset
  962. add si,bx
  963. mov di,offset DG:FCBDOS
  964. call MoveToFCB
  965. pop bx
  966. pop di
  967. pop si
  968. ret
  969. ;
  970. ; Move ASCIZ filename to FCB-type filename from [SI] to [DI].
  971. ;
  972. MoveToFCB:
  973. xor cx,cx
  974. NextChar:
  975. lodsb
  976. cmp al,'.'
  977. jz Fill_Blanks
  978. stosb
  979. inc cx
  980. jmp short NextChar
  981. Fill_Blanks:
  982. mov al,' '
  983. cmp cx,8
  984. jge See_Ext
  985. stosb
  986. inc cx
  987. jmp short Fill_Blanks
  988. See_Ext:
  989. mov cx,3
  990. Next_Ext:
  991. lodsb
  992. stosb
  993. dec cx
  994. jnz Next_Ext
  995. RET
  996. ;
  997. ; Gets source file names from SourceBIOSFile and SourceDOSFile and puts them
  998. ; into the ASCIZ strings SourceBIOSName and SourceDOSName.
  999. ;
  1000. GetSourceNames:
  1001. push si
  1002. push di
  1003. push cx
  1004. mov si,offset DG:SourceBIOSFile
  1005. mov di,offset DG:SourceBIOSName
  1006. add di,3 ; skip over drive,colon,back-slash
  1007. mov cx,12
  1008. repe movsb
  1009. mov si,offset DG:SourceDOSFile
  1010. mov di,offset DG:SourceDOSName
  1011. add di,3 ; skip over drive,colon,back-slash
  1012. mov cx,12
  1013. repe movsb
  1014. pop cx
  1015. pop di
  1016. pop si
  1017. ret
  1018. CODE ENDS
  1019. END START
  1020.