Leaked source code of windows server 2003
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.

575 lines
18 KiB

  1. ;++
  2. ;
  3. ;Module Name:
  4. ;
  5. ; fatnec98.asm
  6. ;
  7. ;Abstract:
  8. ;
  9. ; The ROM in NEC PC-9800 starts the boot process by performing a hardware
  10. ; initialization and a verification of all external devices. If all goes
  11. ; well, it will then load from the boot drive the sector from track 0, head 0,
  12. ; sector 1. This sector is placed at physical address 1FC00h or 1FE00h.
  13. ; This start address is decided by boot device.
  14. ;
  15. ; The code in this sector is responsible for locating NTLDR and
  16. ; for placing the directory sector with this information at DirSeg:0.
  17. ; After loading in this sector, it reads in the entirety of the BIOS at
  18. ; BiosSeg:0 and does a long jump to the entry point at BiosSeg:0.
  19. ;
  20. ; There are no error message during execution of this code.
  21. ; In case of NTLDR does not exist or BIOS read error, will sound beep.
  22. ;
  23. ; At the beginning of the boot sector, there is a table which describes the
  24. ; structure of the media. This is equivalent to the BPB with some
  25. ; additional information describing the physical layout of the driver (heads,
  26. ; tracks, sectors)
  27. ;
  28. ;Author:
  29. ;
  30. ;
  31. ;Environment:
  32. ;
  33. ; Real mode
  34. ; FAT file system
  35. ;
  36. ;Revision History:
  37. ;
  38. ; 6/12/97 Tochizawa(NEC) support booting from 1.44MB FD
  39. ;
  40. ;--
  41. page ,132
  42. title boot - NTLDR FAT loader
  43. name fatboot
  44. .8086
  45. DIR_ENT struc
  46. Filename db 11 dup(?)
  47. Attribute db ?
  48. Reserved db 10 dup(?)
  49. Time dw 2 dup(?)
  50. StartCluster dw ?
  51. FileSize dd ?
  52. DIR_ENT ends
  53. ;
  54. ; This is the structure used to pass all shared data between the boot sector
  55. ; and NTLDR.
  56. ;
  57. SHARED struc
  58. ReadClusters dd ? ; function pointer
  59. ReadSectors dd ? ; function pointer
  60. SectorBase dd ? ; starting sector
  61. SHARED ends
  62. DoubleWord struc
  63. lsw dw ?
  64. msw dw ?
  65. DoubleWord ends
  66. SectorSize equ 512 ; sector size
  67. HiRes equ 00001000b
  68. DAFloppy equ 00010000b ; floppy bit in DA
  69. DASCSI equ 00100000b ; SCSI bit in DA
  70. SYS_PORT equ 37h
  71. BootSeg segment at 1fc0h
  72. BootSeg ends
  73. SysSeg segment at 0040h
  74. org 100h
  75. BIOS_FLAG label byte
  76. org 184h
  77. BootDrive98 label byte
  78. SysSeg ends
  79. DirSeg segment at 1000h
  80. DirSeg ends
  81. NtLdrSeg segment at 2000h
  82. NtLdrSeg ends
  83. BootCode segment ;would like to use BootSeg here, but LINK flips its lid
  84. ASSUME CS:BootCode,DS:NOTHING,ES:NOTHING,SS:NOTHING
  85. public FATBOOT
  86. FATBOOT proc far
  87. jmp short Start
  88. nop
  89. ;
  90. ; THE FOLLOWING DATA CONFIGURES THE BOOT PROGRAM
  91. ; FOR ANY TYPE OF DRIVE OR HARDFILE
  92. ;
  93. ; Note that this data is just a place-holder here. The actual values will
  94. ; be filled in by FORMAT or SYS. When installing the boot sector, only the
  95. ; code following the BPB (from Start to the end) should be copied into the
  96. ; first sector.
  97. ;
  98. OsName db "MSWIN"
  99. OsVersion db "4.1"
  100. BPB label byte
  101. BytesPerSector dw SectorSize ; Size of a physical sector
  102. SectorsPerCluster db 8 ; Sectors per allocation unit
  103. ReservedSectors dw 4 ; Number of reserved sectors
  104. Fats db 2 ; Number of fats
  105. DirectoryEntries dw 0c00h ; Number of directory entries
  106. Sectors dw 0 ; No. of sectors - no. of hidden sectors
  107. Media db 0F8H ; Media byte
  108. FatSectors dw 70h ; Number of fat sectors
  109. SectorsPerTrack dw 23h ; Sectors per track
  110. Heads dw 7 ; Number of surfaces
  111. HiddenSectors dd 0f5h ; Number of hidden sectors
  112. SectorsLong dd 369c4h ; Number of sectors iff Sectors = 0
  113. ;
  114. ; The following byte is NOT part of the BPB but is set by SYS and format
  115. ; We should NOT change its position.
  116. ;
  117. ; keep order of DriveNumber and CurrentHead!
  118. DriveNumber db 80h ; Physical drive number (0 or 80h)
  119. CurrentHead db 0 ; Unitialized
  120. Signature db 41 ; Signature Byte for bootsector
  121. BootID dd 0 ; Boot ID field.
  122. Boot_Vol_Label db "NO NAME "
  123. Boot_System_ID db 'FAT12 ' ;
  124. ;
  125. ; We need a shred data area with ntldr/setupldr.
  126. ; But we don't have memory for using data area. Because bootcode size is 512KB.
  127. ; There is nothing for it but to use this area.
  128. ;
  129. NtldrSharedData label dword
  130. Start:
  131. assume DS:nothing,ES:nothing
  132. xor ax, ax ; Setup the stack to a known good spot
  133. mov ss, ax
  134. mov sp, 7c00h
  135. push cs
  136. pop ds
  137. assume DS:BootCode
  138. mov ax, SysSeg
  139. mov es, ax
  140. assume ES:SysSeg
  141. mov al, BootDrive98
  142. mov DriveNumber, al ; boot drive
  143. push si ; save partition info
  144. ; We need some intialization.
  145. mov si, BytesPerSector ; keep it in reg
  146. test al, DAFloppy
  147. jnz Flg00
  148. ; Boot is from hard disk.
  149. ; Our BPB tells us BytesPerSector, but it is a logical value
  150. ; that may differ from the physical value.
  151. ; We need SectorShiftFactor that is used to convert logical sector address
  152. ; to phisical sector address.
  153. mov ah, 84h ; ROM BIOS sense command
  154. xor bx, bx ; initialize bx to 0
  155. int 1Bh ;
  156. jc Flg01
  157. test bx, bx ; physical sector length returned ?
  158. jnz Flg02 ; if not,
  159. Flg01:
  160. mov bx, 256 ; we assume 256 bytes per sector
  161. Flg02:
  162. mov ax, si ; BytesPerSector
  163. xor dx, dx
  164. div bx
  165. mov NtldrSharedData.SectorShiftFactor, ax
  166. mov ax, 32*1024 ; 32KB
  167. ; xor dx, dx ; dx must be 0 here.
  168. div si ; BytesPerSector
  169. mov NtldrSharedData.LogicalSectorsIn32KByte, al
  170. Flg00:
  171. ; The system is now prepared for us to begin reading. First, determine
  172. ; logical sector numbers of the start of the directory and the start of the
  173. ; data area.
  174. ;
  175. ; We read all the directory entries into DirSeg.
  176. ; It might be more than 64KB if hard disk.
  177. mov ax, size DIR_ENT
  178. mul DirectoryEntries ; (dx:ax) = # of bytes in directory
  179. dec si ; (si) = BytesPerSector -1
  180. add ax, si
  181. adc dx, 0
  182. inc si ; (si) = BytesPerSector
  183. div si ; (ax) = # of sectors in directory
  184. mov cx, ax ; save it in cx for later
  185. mov al, Fats
  186. xor ah, ah ; (ax) = # of FATs
  187. mul FatSectors ; (ax) = # of FAT sectors
  188. add ax, ReservedSectors ; (ax) = sector # directory starts
  189. adc dx, 0
  190. ; save it in "Arguments" for later 'Read'
  191. mov NtldrSharedData.Arguments.SectorBase.lsw, ax
  192. mov NtldrSharedData.Arguments.SectorBase.msw, dx
  193. add ax, cx ; next sector after directory
  194. mov NtldrSharedData.ClusterBase, ax ; save it for later use
  195. Rpt00:
  196. push cx ; (cx) = # of sectors in directory
  197. push si ; (si) = BytesPerSector
  198. mov bx, DirSeg
  199. mov es, bx
  200. assume es:DirSeg
  201. xor bx, bx ; (es:bx) -> directory segment
  202. ; NTLDR is supposed to occupy 1st 512 entries
  203. ; in the root directory.
  204. xor dx, dx
  205. mov ax, (512*32) ; (dx:ax) = 4000h
  206. div si ; (si) = BytesPerSector
  207. ;
  208. ; DoRead does a RETF, but LINK pukes if we do a FAR call in a /tiny program.
  209. ;
  210. ; (ax) = # of sectors to read
  211. ;
  212. push ax
  213. push cs ; make retern frame
  214. call DoRead ; read directory
  215. pop ax
  216. jc BootErr$he
  217. ; Now we scan for the presence of NTLDR
  218. xor bx, bx ; offset
  219. mov cx, 512 ; # of entries to search (only 512)
  220. Rpt01:
  221. mov di, bx ; (es:di) = filespec in directory entry
  222. push cx
  223. mov cx, 11 ; (cx) = filespec size
  224. mov si, offset LOADERNAME ; (ds:si) = filespec we are searching
  225. repe cmpsb
  226. pop cx
  227. je @F ; if matches, exit loop
  228. add bx, size DIR_ENT ; else next entry
  229. loop Rpt01
  230. @@:
  231. test cx, cx
  232. pop si
  233. pop cx
  234. jnz Rpt02
  235. add NtldrSharedData.Arguments.SectorBase.lsw, ax
  236. adc NtldrSharedData.Arguments.SectorBase.msw, 0
  237. sub cx, ax
  238. ja Rpt00
  239. jmp BootErr$bnf
  240. Rpt02:
  241. ; We have found NTLDR
  242. ; We read it into NtLdrSeg.
  243. mov dx, es:[bx].StartCluster ; (dx) = starting cluster number
  244. mov ax, 1 ; (ax) = sectors to read
  245. cmp BytesPerSector, 256
  246. jne @F
  247. inc ax ; We need to read 2 sectors
  248. @@:
  249. ;
  250. ; Now, go read the file
  251. ;
  252. mov bx, NtLdrSeg
  253. mov es, bx
  254. assume es:NtLdrSeg
  255. xor bx, bx ; (es:bx) -> start of NTLDR
  256. ;
  257. ; LINK barfs if we do a FAR call in a TINY program, so we have to fake it
  258. ; out by pushing CS.
  259. ;
  260. push dx ; save starting cluster number
  261. push cs ; make retern frame
  262. call ClusterRead
  263. pop bx ; (bx) = Starting Cluster Number
  264. jc BootErr$he
  265. ;
  266. ; NTLDR requires:
  267. ; BX = Starting Cluster Number of NTLDR
  268. ; DL = INT 1B drive number we booted from <- DA/UA in 98
  269. ; DS:SI -> the boot media's BPB
  270. ; DS:DI -> argument structure
  271. ; 1000:0000 - entire DIR is loaded
  272. ; On PC-9801 we have one more parameter...
  273. ; (bp) = partition info
  274. ;
  275. lea si, BPB ; ds:si -> BPB
  276. lea di, NtldrSharedData.Arguments ; ds:di -> Arguments
  277. mov ax,ds
  278. mov NtldrSharedData.Arguments.ReadClusters.msw, ax
  279. mov NtldrSharedData.Arguments.ReadClusters.lsw, offset ClusterRead
  280. mov NtldrSharedData.Arguments.ReadSectors.msw, ax
  281. mov NtldrSharedData.Arguments.ReadSectors.lsw, offset DoRead
  282. mov dl, DriveNumber ; dl = boot drive
  283. pop bp ; partition info
  284. ;
  285. ; FAR JMP to 2000:0003. This is hand-coded, because I can't figure out
  286. ; how to make MASM do this for me. By entering NTLDR here, we skip the
  287. ; initial jump and execute the FAT-specific code to load the rest of
  288. ; NTLDR.
  289. ;
  290. db 0EAh ; JMP FAR PTR
  291. dw 3 ; 2000:3
  292. dw 02000h
  293. FATBOOT endp
  294. ;
  295. ; BootErr - print error message and hang the system.
  296. ;
  297. BootErr proc
  298. BootErr endp
  299. ; BootError - print error message and hang the system.
  300. ;
  301. BootError proc
  302. assume DS:BootCode,ES:nothing
  303. ;
  304. ; Am I display message that is reason of the ERROR ?
  305. ; Ofcourse. but no room available.
  306. BootErr$bnf:
  307. BootErr$he:
  308. mov al, 06h
  309. out 37h, al
  310. jmp $
  311. BootError endp
  312. ;
  313. ; ClusterRead - read AL sectors into ES:BX starting from
  314. ; cluster DX
  315. ;
  316. ClusterRead proc
  317. push ax ; (TOS) = # of sectors to read
  318. dec dx
  319. dec dx ; adjust for reserved clusters 0 and 1
  320. mov al, SectorsPerCluster
  321. xor ah, ah
  322. mul dx ; DX:AX = starting sector number
  323. add ax, NtldrSharedData.ClusterBase ; adjust for FATs, root dir, boot sec.
  324. adc dx, 0
  325. mov NtldrSharedData.Arguments.SectorBase.lsw, ax
  326. mov NtldrSharedData.Arguments.SectorBase.msw, dx
  327. pop ax ; (al) = # of sectors to read
  328. ;
  329. ; Now we've converted the cluster number to a SectorBase, so just fall
  330. ; through into DoRead
  331. ;
  332. ClusterRead endp
  333. ;
  334. ; DoRead - read AL sectors into ES:BX starting from sector
  335. ; SectorBase.
  336. ;
  337. DoRead proc
  338. xor ah, ah
  339. cmp ax, 0
  340. jnz @F
  341. inc ah ; read 256 Sectors
  342. @@:
  343. push si
  344. push di
  345. push bp
  346. mov si, ax
  347. mov bp, bx
  348. mov cx, NtldrSharedData.Arguments.SectorBase.lsw ; Starting sector
  349. mov dx, NtldrSharedData.Arguments.SectorBase.msw ; Starting sector
  350. ; (dx:cx) = logical sector # relative to partition
  351. ; (si) = # of sectors to read
  352. ; (es:bp) = read buffer
  353. Rpt03:
  354. push dx
  355. push cx
  356. ; [sp] = logical sector number LSW
  357. ; [sp+2] = logical sector number MSW
  358. mov al, DriveNumber
  359. test al, DAFloppy
  360. jz Flg03
  361. ; We are reading floppy disk.
  362. ; We don't care about DMA boundary, as no PC-9801 DOS floppy disk
  363. ; has more than 2048 directory entries, we never read
  364. ; more than 64 KB.
  365. push ax
  366. mov ax, cx ; (dx:ax) = lsn
  367. mov bx, SectorsPerTrack
  368. div bx ; (dx) = sector # (0-based)
  369. ; (ax) = cylinder # * # of heads + head #
  370. div byte ptr Heads ;(ah) = head address
  371. ; (al) = cylinder address
  372. mov dh, ah
  373. mov cl, al
  374. mov al, byte ptr BytesPerSector + 1 ; convert Bytes/Sector to
  375. xor ch, ch ; SectorLengthID
  376. whl00: ; Bytes/Sect | ID (ch)
  377. cmp al, 0
  378. jz @f
  379. inc ch ; 128 -> 0
  380. shr al, 1 ; 256 -> 1
  381. jmp short whl00 ; 512 -> 2
  382. @@: ; 1024 -> 3
  383. pop ax
  384. sub bl, dl ; sectors in THIS track
  385. inc dl ; sector # (1-based)
  386. ; We have prepared following ROM BIOS parameters
  387. ; (al) = drive
  388. ; (cl) = cylinder address
  389. ; (ch) = sector size
  390. ; (dl) = sector address
  391. ; (dh) = head address
  392. ; (es:bp) -> buffer
  393. ;
  394. ; And we have some more.
  395. ; (bl) = # of sectors we can read with 1 time ROM call
  396. ; (si) = # of sectors we need to read
  397. ;
  398. jmp short Flg04
  399. Flg03:
  400. ; We are reading hard disk.
  401. ; We don't care about DMA boundary
  402. ; as length we read is 64KB max.
  403. ;
  404. and al, 7FH ; drive #
  405. mov bx,NtldrSharedData.SectorShiftFactor
  406. Rpt04: ; logical sector address to
  407. shr bx, 1
  408. jc @F
  409. shl cx, 1 ; physical sector address
  410. rcl dx, 1
  411. jmp short Rpt04
  412. @@:
  413. add cx, HiddenSectors.lsw
  414. adc dx, HiddenSectors.msw ; (dx:cx) -> relative to drive
  415. mov bl, NtldrSharedData.LogicalSectorsIn32KByte
  416. ; sectors we can read (32KB)
  417. ; this is not optimum on performance
  418. ; We have prepared following ROM BIOS parameters
  419. ; (al) = drive
  420. ; (dx:cx) = relative sector number
  421. ; (es:bp) -> buffer
  422. ;
  423. ; And we have some more.
  424. ; (bl) = # of sectors we can read with 1 time ROM call
  425. ; (si) = # of sectors we need to read
  426. ;
  427. Flg04:
  428. xor bh, bh
  429. cmp si, bx
  430. jnb @F
  431. mov bx, si
  432. @@:
  433. push bx ; # of sectors we are reading this call
  434. push dx
  435. xchg ax, bx
  436. mul BytesPerSector
  437. xchg ax, bx
  438. pop dx
  439. push bx ; # of bytes.
  440. ; [sp] = # of bytes to read
  441. ; [sp+2] = # of sectors
  442. ; [sp+4] = logical sector number LSW
  443. ; [sp+6] = logical sector number MSW
  444. mov ah, 01010110b ; read
  445. int 1BH
  446. pop di ; # of bytes
  447. pop bx ; # of sectors
  448. pop cx ; lsn (LSW)
  449. pop dx ; lsn (MSW)
  450. jc @F ; return Carry
  451. ; prepare for next call
  452. add cx, bx ; advance lsn
  453. adc dx, 0 ;
  454. add bp, di ; advance offset
  455. sub si, bx ; decrement # of sectors
  456. jnz Rpt03 ; CarryFlag is Clear
  457. @@:
  458. pop bp
  459. pop di
  460. pop si
  461. retf
  462. DoRead endp
  463. LOADERNAME DB "NTLDR "
  464. ; .errnz ($-FATBOOT) GT 510,<FATAL PROBLEM: boot sector is too large>
  465. org 510
  466. db 55h, 0aah
  467. BootCode ends
  468. ;Unitialized variables go here--beyond the end of the boot sector in free memory
  469. UninitializedWork struc
  470. ClusterBase dw ? ; first sector of cluster # 2
  471. SectorShiftFactor dw ?
  472. LogicalSectorsIn32KByte db ?
  473. Arguments db (size SHARED) dup (?) ; structure passed to NTLDR
  474. UninitializedWork ends
  475. END FATBOOT