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.

386 lines
10 KiB

5 years ago
  1. ; SCCSID = @(#)ibmboot.asm 1.1 85/05/13
  2. TITLE BOOT SECTOR 1 OF TRACK 0 - BOOT LOADER
  3. ; Rev 1.0 ChrisP, AaronR and others. 2.0 format boot
  4. ;
  5. ; Rev 3.0 MarkZ Salmon enhancements
  6. ; 2.50 in label
  7. ; Rev 3.1 MarkZ 3.1 in label due to vagaries of SYSing to IBM drive D's
  8. ; This resulted in the BPB being off by 1. So we now trust
  9. ; 2.0 and 3.1 boot sectors and disbelieve 3.0.
  10. ;
  11. ; Rev 3.2 LeeAc Modify layout of extended BPB for >32M support
  12. ; Move PHYDRV to 3rd byte from end of sector
  13. ; so that it won't have to be moved again
  14. ; FORMAT and SYS count on PHYDRV being in a known location
  15. ;
  16. ; Rev. 3.3 DCLove Changed Sec 9 EOT field from 15 to 18. May 29, 1986.
  17. ;
  18. ; Rev 3.31 MarkT The COUNT value has a bogus check (JBE????) to determine
  19. ; if we've loaded in all the sectors of IO.SYS. This will
  20. ; cause too big of a load if the sectors per track is high
  21. ; enough, causing either a stack overflow or the boot code
  22. ; to be overwritten.
  23. ;
  24. ;
  25. ; The ROM in the IBM PC starts the boot process by performing a hardware
  26. ; initialization and a verification of all external devices. If all goes
  27. ; well, it will then load from the boot drive the sector from track 0, head 0,
  28. ; sector 1. This sector is placed at physical address 07C00h. The initial
  29. ; registers are set up as follows: CS=DS=ES=SS=0. IP=7C00h, SP=0400H.
  30. ;
  31. ; The code in this sector is responsible for locating the MSDOS device drivers
  32. ; (IO.SYS) and for placing the directory sector with this information at
  33. ; physical address 00500h. After loading in this sector, it reads in the
  34. ; entirety of the BIOS at BIOSEG:0 and does a long jump to that point.
  35. ;
  36. ; If no BIOS/DOS pair is found an error message is displayed and the user is
  37. ; prompted to reinsert another disk. If there is a disk error during the
  38. ; process, a message is displayed and things are halted.
  39. ;
  40. ; At the beginning of the boot sector, there is a table which describes the
  41. ; MSDOS structure of the media. This is equivalent to the BPB with some
  42. ; additional information describing the physical layout of the driver (heads,
  43. ; tracks, sectors)
  44. ;
  45. ORIGIN EQU 7C00H ; Origin of bootstrap LOADER
  46. BIOSEG EQU 70H ; destingation segment of BIOS
  47. BioOff EQU 700H ; offset of bios
  48. cbSec EQU 512
  49. cbDirEnt EQU 32
  50. DirOff EQU 500h
  51. ;
  52. ; Define the destination segment of the BIOS, including the initialization
  53. ; label
  54. ;
  55. SEGBIOS SEGMENT AT BIOSEG
  56. BIOS LABEL BYTE
  57. SEGBIOS ENDS
  58. CODE SEGMENT
  59. ASSUME CS:CODE,DS:NOTHING,ES:NOTHING,SS:NOTHING
  60. ORG DirOff + 1Ch
  61. BiosFS LABEL WORD
  62. ORG ORIGIN
  63. DSKADR = 1EH*4 ;POINTER TO DRIVE PARAMETERS
  64. Public $START
  65. $START:
  66. JMP START
  67. ;----------------------------------------------------------
  68. ;
  69. ; THE FOLLOWING DATA CONFIGURES THE BOOT PROGRAM
  70. ; FOR ANY TYPE OF DRIVE OR HARDFILE
  71. ;
  72. DB "MSDOS"
  73. DB "3.3"
  74. ByteSec DW cbSec ; SIZE OF A PHYSICAL SECTOR
  75. DB 8 ; SECTORS PER ALLOCATION UNIT
  76. cSecRes DW 1 ; NUMBER OF RESERVED SECTORS
  77. cFat DB 2 ; NUMBER OF FATS
  78. DirNum DW 512 ; NUMBER OF DIREC ENTRIES
  79. DW 4*17*305-1 ; NUMBER OF SECTORS - NUMBER OF HIDDEN SECTORS
  80. MEDIA DB 0F8H ; MEDIA BYTE
  81. cSecFat DW 8 ; NUMBER OF FAT SECTORS
  82. SECLIM DW 17 ; SECTORS PER TRACK
  83. HDLIM DW 4 ; NUMBER OF SURFACES
  84. cSecHid DW 1 ; NUMBER OF HIDDEN SECTORS
  85. dw 0 ; high order word of Hiden Sectors
  86. dd 0 ; 32 bit version of NUMBER OF SECTORS
  87. ; (when 16 bit version is zero)
  88. db 6 dup(?) ; reserved for later expansion
  89. CURHD DB ? ; Unitialized
  90. ; this is an image of the disk parameter table. Zero entries are copied
  91. ; from the rom table at boot.
  92. ;
  93. SEC9 DB 0 ; DISK_SPECIFY_1
  94. DB 0 ; DISK_SPECIFY_2
  95. DB 0 ; DISK_MOTOR_WAIT
  96. DB 0 ; DISK_SECTOR_SIZ
  97. DB 12h ; DISK_EOT
  98. DB 0 ; DISK_RW_GAP
  99. DB 0 ; DISK_DTL
  100. DB 0 ; DISK_FORMT_GAP
  101. DB 0 ; DISK_FILL
  102. DB 1 ; DISK_HEAD_STTL
  103. DB 0 ; DISK_MOTOR_STRT
  104. Public UDATA
  105. UDATA LABEL WORD
  106. BIOS$ EQU WORD PTR UDATA+1
  107. CURTRK EQU WORD PTR UDATA+3
  108. CURSEC EQU BYTE PTR UDATA+5
  109. COUNT EQU BYTE PTR UDATA+6 ; NUMBER OF BIOS SECTORS
  110. BIOSAV EQU WORD PTR UDATA+7
  111. DIR$ EQU WORD PTR UDATA+9
  112. START:
  113. ;
  114. ; First thing is to reset the stack to a better and more known place. The ROM
  115. ; may change, but we'd like to get the stack in the correct place.
  116. ;
  117. CLI ;Stop interrupts till stack ok
  118. XOR AX,AX
  119. MOV SS,AX ;Work in stack just below this routine
  120. ASSUME SS:CODE
  121. MOV SP,ORIGIN
  122. PUSH SS
  123. POP ES
  124. ASSUME ES:CODE
  125. ;
  126. ; We copy the disk parameter table into a local area. We scan the table above
  127. ; for non-zero parameters. Any we see get changed to their non-zero values.
  128. ;
  129. MOV BX,DSKADR
  130. LDS SI,DWORD PTR SS:[BX] ; get address of disk table
  131. PUSH DS ; save original vector for possible
  132. PUSH SI ; restore
  133. PUSH SS
  134. PUSH BX
  135. MOV DI,OFFSET Sec9
  136. MOV CX,11
  137. CLD
  138. changeloop:
  139. LODSB
  140. CMP BYTE PTR ES:[DI],0 ; is the template zero?
  141. JZ Store ; yes, store what we've got
  142. MOV AL,ES:[DI]
  143. Store:
  144. STOSB
  145. MOV AL,AH
  146. LOOP ChangeLoop
  147. ;
  148. ; Place in new disk parameter table.
  149. ;
  150. PUSH ES
  151. POP DS
  152. ASSUME DS:CODE
  153. MOV [BX+2],AX
  154. MOV [BX],OFFSET SEC9
  155. ;
  156. ; We may now turn interrupts back on. Before this, there is a small window
  157. ; when a reboot command may come in when the disk parameter table is garbage
  158. ;
  159. STI ;Interrupts OK now
  160. ;
  161. ; Reset the disk system just in case any thing funny has happened.
  162. ;
  163. INT 13H ;Reset the system
  164. JC RERROR
  165. ;
  166. ; The system is now prepared for us to begin reading. First, determine
  167. ; logical sector numbers of the start of the directory and the start of the
  168. ; data area.
  169. ;
  170. MOV AL,cFat ;Determine sector dir starts on
  171. CBW
  172. MUL cSecFat
  173. ADD AX,cSecHid
  174. ADD AX,cSecRes
  175. MOV [DIR$],AX ; AX = cFat*cSecFat + cSecRes + cSecHid
  176. MOV [BIOS$],AX
  177. ;
  178. ; Take into account size of directory (only know number of directory entries)
  179. ;
  180. MOV AX,cbDirEnt ; bytes per directory entry
  181. MUL DirNum ; convert to bytes in directory
  182. MOV BX,ByteSec ; add in sector size
  183. ADD AX,BX
  184. DEC AX ; decrement so that we round up
  185. DIV BX ; convert to sector number
  186. ADD [BIOS$],AX
  187. ;
  188. ; We load in the first directory sector and examine it to make sure the the
  189. ; BIOS and DOS are the first two directory entries. If they are not found,
  190. ; the user is prompted to insert a new disk. The directory sector is loaded
  191. ; into 00500h
  192. ;
  193. MOV BX,DirOff ; sector to go in at 00500h
  194. MOV AX,DIR$ ; logical sector of directory
  195. CALL DODIV ; convert to sector, track, head
  196. MOV AX,0201H ; disk read 1 sector
  197. CALL DOCALL ; do the disk read
  198. JB CKERR ; if errors try to recover
  199. ;
  200. ; Now we scan for the presence of IO.SYS and MSDOS.SYS. Check the
  201. ; first directory entry.
  202. ;
  203. MOV DI,BX
  204. MOV CX,11
  205. MOV SI,OFFSET BIO ; point to "bios com"
  206. REPZ CMPSB ; see if the same
  207. JNZ CKERR ; if not there advise the user
  208. ;
  209. ; Found the BIOS. Check the second directory entry.
  210. ;
  211. LEA DI,[BX+20h]
  212. MOV SI,OFFSET DOS ; point to "86dos com"
  213. MOV CX,11
  214. REPZ CMPSB
  215. JZ DoLoad
  216. ;
  217. ; There has been some recoverable error. Display a message and wait for a
  218. ; keystroke.
  219. ;
  220. CKERR: MOV SI,OFFSET SYSMSG ; point to no system message
  221. ErrOut: CALL WRITE ; and write on the screen
  222. XOR AH,AH ; wait for response
  223. INT 16H ; get character from keyboard
  224. POP SI ; reset disk parameter table back to
  225. POP DS ; rom
  226. POP [SI]
  227. POP [SI+2]
  228. INT 19h ; Continue in loop till good disk
  229. RERROR: MOV SI,OFFSET DMSSG ; DISK ERROR MESSAGE
  230. JMP ErrOut
  231. ;
  232. ; We now begin to load the BIOS in. Compute the number of sectors needed
  233. ;
  234. DoLoad:
  235. MOV AX,BiosFS ; get file size
  236. XOR DX,DX ; presume < 64K
  237. DIV ByteSec ; convert to sectors
  238. INC AL ; reading in one more can't hurt
  239. MOV COUNT,AL ; Store running count
  240. MOV AX,BIOS$ ; get logical sector of beginning of BIOS
  241. MOV BIOSAV,AX ; store away for real bios later
  242. MOV BX,BioOff ; Load address from BIOSSEG
  243. ;
  244. ; Main read-in loop.
  245. ; ES:BX points to area to read.
  246. ; Count is the number of sectors remaining.
  247. ; BIOS$ is the next logical sector number to read
  248. ;
  249. LOOPRD:
  250. MOV AX,BIOS$ ; Starting sector
  251. CALL DODIV
  252. ;
  253. ; CurHD is the head for this next disk request
  254. ; CurTrk is the track for this next request
  255. ; CurSec is the beginning sector number for this request
  256. ;
  257. ; Compute the number of sectors that we may be able to read in a single ROM
  258. ; request.
  259. ;
  260. MOV AX,SECLIM
  261. SUB AL,CURSEC
  262. INC AX
  263. ;
  264. ; AX is the number of sectors that we may read.
  265. ;
  266. ;
  267. ;New code for Rev 3.31
  268. ;*****************************************************************************
  269. CMP COUNT,AL ;Is sectors we can read more than we need?
  270. JAE GOT_SECTORS ;No, it is okay
  271. MOV AL,COUNT ;Yes, only read in what is left
  272. GOT_SECTORS:
  273. ;*****************************************************************************
  274. ;End of change
  275. ;
  276. PUSH AX
  277. CALL DOCALL
  278. POP AX
  279. JB RERROR ; If errors report and go to ROM BASIC
  280. SUB COUNT,AL ; Are we finished?
  281. ;
  282. ;Old code replaced by Rev 3.3
  283. ;********************************************************************
  284. ; JBE DISKOK ; Yes -- transfer control to the DOS
  285. ;********************************************************************
  286. ;New code for Rev 3.3
  287. ;
  288. JZ DISKOK ; Yes -- transfer control to the DOS
  289. ;********************************************************************
  290. ;End of change
  291. ;
  292. ADD BIOS$,AX ; increment logical sector position
  293. MUL ByteSec ; determine next offset for read
  294. ADD BX,AX ; (BX)=(BX)+(SI)*(Bytes per sector)
  295. JMP LOOPRD ; Get next track
  296. ;
  297. ; IBMINIT requires the following input conditions:
  298. ;
  299. ; DL = INT 13 drive number we booted from
  300. ; CH = media byte
  301. ; BX = First data sector on disk (0-based)
  302. ;
  303. DISKOK:
  304. MOV CH,Media
  305. MOV DL,PhyDrv
  306. MOV BX,[BIOSAV] ;Get bios sector in bx
  307. JMP FAR PTR BIOS ;CRANK UP THE DOS
  308. WRITE: LODSB ;GET NEXT CHARACTER
  309. OR AL,AL ;clear the high bit
  310. JZ ENDWR ;ERROR MESSAGE UP, JUMP TO BASIC
  311. MOV AH,14 ;WILL WRITE CHARACTER & ATTRIBUTE
  312. MOV BX,7 ;ATTRIBUTE
  313. INT 10H ;PRINT THE CHARACTER
  314. JMP WRITE
  315. ;
  316. ; convert a logical sector into Track/sector/head. AX has the logical
  317. ; sector number
  318. ;
  319. DODIV:
  320. XOR DX,DX
  321. DIV SECLIM
  322. INC DL ; sector numbers are 1-based
  323. MOV CURSEC,DL
  324. XOR DX,DX
  325. DIV HDLIM
  326. MOV CURHD,DL
  327. MOV CURTRK,AX
  328. ENDWR: RET
  329. ;
  330. ; Issue one read request. ES:BX have the transfer address, AL is the number
  331. ; of sectors.
  332. ;
  333. DOCALL: MOV AH,2
  334. MOV DX,CURTRK
  335. MOV CL,6
  336. SHL DH,CL
  337. OR DH,CURSEC
  338. MOV CX,DX
  339. XCHG CH,CL
  340. MOV DL, PHYDRV
  341. mov dh, curhd
  342. INT 13H
  343. RET
  344. include messages.inc
  345. BIO DB "IO SYS"
  346. DOS DB "MSDOS SYS"
  347. Free EQU (cbSec - 3) - ($-$start)
  348. if Free LT 0
  349. %out FATAL PROBLEM:boot sector is too large
  350. endif
  351. org origin + (cbSec - 3)
  352. ; FORMAT and SYS count on PHYDRV being right here
  353. PHYDRV db 0
  354. ; Boot sector signature
  355. db 55h,0aah
  356. CODE ENDS
  357. END