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.

1773 lines
38 KiB

  1. ;++
  2. ;
  3. ; Module name
  4. ;
  5. ; exp.asm
  6. ;
  7. ; Author
  8. ;
  9. ; Thomas Parslow (tomp) Feb-26-91
  10. ;
  11. ; Description
  12. ;
  13. ; Entry points exported to OS loader by SU module. Exported
  14. ; routines provide basic machine dependent i/o funtions needed
  15. ; by the OS loader. Providing these routines decouples the
  16. ; OS loader from the h/w. Note that the OS loader will
  17. ; refer to these exported routines as the "external services".
  18. ;
  19. ;
  20. ; Exported Procedures
  21. ;
  22. ; RebootProcessor - Reboots the machine
  23. ; GetSector - Read one or more sectors from the boot device.
  24. ; PutChar - Puts a character on the video display.
  25. ; GetKey - Gets a key from the keyboard
  26. ; GetCounter - Reads the Tick Counter
  27. ; Reboot - Transfers control to a loaded boot sector.
  28. ; HardwareCursor - set position of hardware cursor
  29. ; GetDateTime - gets date and time
  30. ; ComPort - int14 functions
  31. ; GetStallCount - calculates processor stall count
  32. ;
  33. ;
  34. ; Notes
  35. ;
  36. ; When adding a new exported routine note that you must manually add the
  37. ; entry's name to the BootRecord in "sudata.asm".
  38. ;
  39. ;--
  40. include su.inc
  41. include macro.inc
  42. DISK_TABLE_VECTOR equ 01Eh * 4
  43. _TEXT segment para use16 public 'CODE'
  44. ASSUME CS: _TEXT, DS: DGROUP, SS: DGROUP
  45. .386p
  46. extrn _DiskBaseTable:near
  47. extrn _RomDiskBasePointer:near
  48. extrn _EddsAddressPacket:near
  49. ;++
  50. ;
  51. ; Exported Name:
  52. ;
  53. ; RebootProcessor
  54. ;
  55. ; Arguments:
  56. ;
  57. ; None
  58. ;
  59. ; Description:
  60. ;
  61. ; Reboot the processor using INT 19h
  62. ;
  63. ;
  64. ;
  65. ;--
  66. ;
  67. ; ExportEntry takes us from a 32bit cs to a 16bit cs, inits 16bit stack
  68. ; and ds segments and saves the callers esp and ebp.
  69. ;
  70. ;--
  71. EXPORT_ENTRY_MACRO RebootProcessor
  72. ;
  73. ; Switch to real mode so we can take interrupts
  74. ;
  75. ENTER_REALMODE_MACRO
  76. ;
  77. ; int 19h doesn't do what you would expect on BIOS Boot Specification machines.
  78. ; It either goes on to the next boot device or goes back to the first boot
  79. ; device. In both cases, it does not properly reset the machine. So we write
  80. ; to the keyboard port instead (as does HalpReboot).
  81. ;
  82. ; int 19h
  83. mov ax, 040h
  84. mov ds, ax
  85. mov word ptr ds:[72h], 1234h ; set location 472 to 1234 to indicate warm reboot
  86. mov al, 0feh
  87. out 64h, al ; write to keyboard port to cause reboot
  88. ;
  89. ; Loop forever and wait to ctrl-alt-del (should never get here)
  90. ;
  91. WAIT_FOREVER_MACRO
  92. ;EXPORT_EXIT_MACRO
  93. ;++
  94. ;
  95. ; Name:
  96. ;
  97. ; GetSector
  98. ;
  99. ; Description:
  100. ;
  101. ; Reads the requested number of sectors from the specified drive into
  102. ; the specified buffer.
  103. ;
  104. ; Arguments:
  105. ;
  106. ; ULONG Virtual address into which to read data
  107. ; ULONG Number of sectors to read
  108. ; ULONG Physical sector number
  109. ; ULONG Drive Number
  110. ; ULONG Function Number
  111. ; TOS -> ULONG Flat return address (must be used with KeCodeSelector)
  112. ;
  113. ;--
  114. EXPORT_ENTRY_MACRO GetSector
  115. ;
  116. ; Move the arguments from the caller's 32bit stack to the SU module's
  117. ; 16bit stack.
  118. ;
  119. MAKE_STACK_FRAME_MACRO <GetSectorFrame>, ebx
  120. ;
  121. ; Go into real mode. We still have the same stack and sp
  122. ; but we'll be executing in realmode.
  123. ;
  124. ENTER_REALMODE_MACRO
  125. ;
  126. ; Get the requested sectors. Arguments on realmode stack
  127. ; Make (bp) point to the bottom of the argument frame.
  128. ;
  129. push bp
  130. mov bp,sp
  131. add bp,2
  132. ;
  133. ; Put the buffer pointer into es:bx. Note that and buffer
  134. ; addresses passed to this routine MUST be in the lower one
  135. ; megabyte of memory to be addressable in real mode.
  136. ;
  137. mov eax,[bp].BufferPointer
  138. mov bx,ax
  139. and bx,0fh
  140. shr eax,4
  141. mov es,ax
  142. ;
  143. ; Place the upper 2 bits of the 10bit track/cylinder number
  144. ; into the uppper 2 bits of the SectorNumber as reguired by
  145. ; the bios.
  146. ;
  147. mov cx,word ptr [bp].TrackNumber
  148. xchg ch,cl
  149. shl cl,6
  150. add cl,byte ptr [bp].SectorNumber
  151. ;
  152. ; Get the rest of the arguments
  153. ;
  154. mov ah,byte ptr [bp].FunctionNumber
  155. mov al,byte ptr [bp].NumberOfSectors
  156. mov dh,byte ptr [bp].HeadNumber
  157. mov dl,byte ptr [bp].DriveNumber
  158. ;
  159. ; Check to see if we are trying to reset/read/write/verify off the second
  160. ; floppy drive. If so, we need to go change the disk-base vector.
  161. ;
  162. cmp dl,1
  163. jne gs3
  164. cmp ah,4
  165. jg gs3
  166. cmp ah,0
  167. je gs1
  168. cmp ah,2
  169. jl gs3
  170. gs1:
  171. ;
  172. ; We need to point the BIOS disk-table vector to our own table for this
  173. ; drive.
  174. ;
  175. push es
  176. push bx
  177. push di
  178. push 0
  179. pop es
  180. mov di, offset DGROUP:_RomDiskBasePointer
  181. mov bx,es:[DISK_TABLE_VECTOR]
  182. mov [di],bx
  183. mov bx,es:[DISK_TABLE_VECTOR+2]
  184. mov [di+2],bx
  185. mov bx,offset DGROUP:_DiskBaseTable
  186. mov es:[DISK_TABLE_VECTOR],bx
  187. mov bx,ds
  188. mov es:[DISK_TABLE_VECTOR+2],bx
  189. pop di
  190. pop bx
  191. pop es
  192. int BIOS_DISK_INTERRUPT
  193. push es
  194. push bx
  195. push di
  196. push 0
  197. pop es
  198. mov di, offset DGROUP:_RomDiskBasePointer
  199. mov bx, [di]
  200. mov es:[DISK_TABLE_VECTOR],bx
  201. mov bx, [di+2]
  202. mov es:[DISK_TABLE_VECTOR+2],bx
  203. pop di
  204. pop bx
  205. pop es
  206. jc gs5
  207. xor eax,eax
  208. jmp short gs5
  209. gs3:
  210. ;
  211. ; Call the bios to read the sector now
  212. ;
  213. if 0
  214. push ax
  215. push dx
  216. push cx
  217. push bx
  218. push es
  219. extrn _DisplayArgs:near
  220. call _DisplayArgs
  221. pop es
  222. pop bx
  223. pop cx
  224. pop dx
  225. pop ax
  226. endif
  227. int BIOS_DISK_INTERRUPT
  228. jc gs5
  229. ;
  230. ; Carry wasn't set so we have no error and need to "clean" eax of
  231. ; any garbage that may have been left in it.
  232. ;
  233. xor eax,eax
  234. gs5:
  235. if 0
  236. push ax
  237. push dx
  238. push cx
  239. push bx
  240. push es
  241. extrn _DisplayArgs:near
  242. call _DisplayArgs
  243. pop es
  244. pop bx
  245. pop cx
  246. pop dx
  247. pop ax
  248. endif
  249. ;
  250. ; Mask-off any garbage that my have been left in the upper
  251. ; 16bits of eax.
  252. ;
  253. and eax,0000ffffh
  254. ;
  255. ; Restore bp and remove stack-frame from stack
  256. ;
  257. pop bp
  258. REMOVE_STACK_FRAME_MACRO <GetSectorFrame>
  259. ;
  260. ; Save return code on 16bit stack
  261. ; Re-enable protect-mode and paging.
  262. ;
  263. ; move cx into high 16-bits of ecx, and dx into cx. This is so the loader
  264. ; can get at interesting values in dx, even though edx gets munged by the
  265. ; random real-mode macros.
  266. shl ecx, 16
  267. mov cx,dx
  268. push eax
  269. RE_ENABLE_PAGING_MACRO
  270. pop eax
  271. ;
  272. ; Return to caller and the 32bit universe.
  273. ;
  274. EXPORT_EXIT_MACRO
  275. ;++
  276. ;
  277. ; Name:
  278. ;
  279. ; GetEddsSector
  280. ;
  281. ; Description:
  282. ;
  283. ; Reads the requested number of sectors from the specified drive into
  284. ; the specified buffer based on the Phoenix Enhanced Disk Drive Spec.
  285. ;
  286. ; Arguments:
  287. ;
  288. ; ULONG xint13 function number (42 = read, 43 = write)
  289. ; ULONG Virtual address into which to read data
  290. ; ULONG Number of logical blocks to read (word)
  291. ; ULONG Logical block number (High dword)
  292. ; ULONG Logical block number (Low dword)
  293. ; ULONG Drive Number (byte)
  294. ; TOS -> ULONG Flat return address (must be used with KeCodeSelector)
  295. ;
  296. ;--
  297. EXPORT_ENTRY_MACRO GetEddsSector
  298. ;
  299. ; Move the arguments from the caller's 32bit stack to the SU module's
  300. ; 16bit stack.
  301. ;
  302. MAKE_STACK_FRAME_MACRO <GetEddsSectorFrame>, ebx
  303. ;
  304. ; Go into real mode. We still have the same stack and sp
  305. ; but we'll be executing in realmode.
  306. ;
  307. ENTER_REALMODE_MACRO
  308. ;
  309. ; Get the requested sectors. Arguments on realmode stack
  310. ; Make (bp) point to the bottom of the argument frame.
  311. ;
  312. push bp
  313. mov bp,sp
  314. add bp,2
  315. push ds
  316. push si
  317. push bx
  318. ;
  319. ; Set up DS:SI -> Disk Address Packet
  320. ;
  321. push 0
  322. pop ds
  323. mov si, offset DGROUP:_EddsAddressPacket
  324. mov ds:[si],word ptr 10h ; Packet size = 10h, plus reserved byte
  325. mov ax,word ptr [bp].NumberOfBlocks
  326. mov ds:[si][2],ax ; Num blocks to transfer
  327. mov eax,[bp].BufPointer
  328. mov bx,ax
  329. and bx,0fh
  330. mov ds:[si][4],bx ; Transfer buffer address (low word=offset)
  331. shr eax,4
  332. mov ds:[si][6],ax ; Transfer buffer address (high word=segment)
  333. mov eax,[bp].LBNLow
  334. mov ds:[si][8],eax ; Starting logical block number (low dword)
  335. mov eax,[bp].LBNHigh
  336. mov ds:[si][12],eax ; Starting logical block number (high dword)
  337. ;
  338. ; Call the bios to read the sector now (DS:SI -> Disk address packet)
  339. ;
  340. mov ah,byte ptr [bp].FunctionNum ; function
  341. xor al,al ; force verify on write off
  342. mov dl,byte ptr [bp].DriveNum ; DL = drive number
  343. int BIOS_DISK_INTERRUPT
  344. jc geserror1
  345. ;
  346. ; Carry wasn't set so we have no error and need to "clean" eax of
  347. ; any garbage that may have been left in it.
  348. ;
  349. xor eax,eax
  350. geserror1:
  351. ;
  352. ; Mask-off any garbage that my have been left in the upper
  353. ; 16bits of eax.
  354. ;
  355. and eax,0000ffffh
  356. pop bx
  357. pop si
  358. pop ds
  359. ;
  360. ; Restore bp and remove stack-frame from stack
  361. ;
  362. pop bp
  363. REMOVE_STACK_FRAME_MACRO <GetEddsSectorFrame>
  364. ;
  365. ; Save return code on 16bit stack
  366. ; Re-enable protect-mode and paging.
  367. ;
  368. ; move cx into high 16-bits of ecx, and dx into cx. This is so the loader
  369. ; can get at interesting values in dx, even though edx gets munged by the
  370. ; random real-mode macros.
  371. shl ecx, 16
  372. mov cx,dx
  373. push eax
  374. RE_ENABLE_PAGING_MACRO
  375. pop eax
  376. ;
  377. ; Return to caller and the 32bit universe.
  378. ;
  379. EXPORT_EXIT_MACRO
  380. ;++
  381. ;
  382. ; Routine Name:
  383. ;
  384. ; GetKey
  385. ;
  386. ; Description:
  387. ;
  388. ; Checks the keyboard to see if a key is available.
  389. ;
  390. ; Arguments:
  391. ;
  392. ; None.
  393. ;
  394. ; Returns:
  395. ;
  396. ; If no key is available, returns 0
  397. ;
  398. ; If ASCII character is available, LSB 0 is ASCII code
  399. ; LSB 1 is keyboard scan code
  400. ; If extended character is available, LSB 0 is extended ASCII code
  401. ; LSB 1 is keyboard scan code
  402. ;
  403. ;--
  404. EXPORT_ENTRY_MACRO GetKey
  405. ;
  406. ; Go into real mode. We still have the same stack and sp
  407. ; but we'll be executing in real mode.
  408. ;
  409. ENTER_REALMODE_MACRO
  410. ;
  411. ; Set up registers to call BIOS and check to see if a key is available
  412. ;
  413. mov ax,0100h
  414. int BIOS_KEYBOARD_INTERRUPT
  415. jnz GkKeyAvail
  416. mov eax, 0
  417. jmp GkDone
  418. GkKeyAvail:
  419. ;
  420. ; Now we call BIOS again, this time to get the key from the keyboard buffer
  421. ;
  422. mov ax,0h
  423. int BIOS_KEYBOARD_INTERRUPT
  424. and eax,0000ffffh
  425. ;
  426. ; Save return code on 16bit stack
  427. ; Re-enable protect mode and paging
  428. ;
  429. GkDone:
  430. push eax
  431. RE_ENABLE_PAGING_MACRO
  432. pop eax
  433. ;
  434. ; Return to caller and the 32-bit universe
  435. ;
  436. EXPORT_EXIT_MACRO
  437. ;++
  438. ;
  439. ; Routine Name:
  440. ;
  441. ; GetCounter
  442. ;
  443. ; Description:
  444. ;
  445. ; Reads the tick counter (incremented 18.2 times per second)
  446. ;
  447. ; Arguments:
  448. ;
  449. ; None
  450. ;
  451. ; Returns:
  452. ;
  453. ; The current value of the tick counter
  454. ;
  455. ;--
  456. EXPORT_ENTRY_MACRO GetCounter
  457. ;
  458. ; Go into real mode.
  459. ;
  460. ENTER_REALMODE_MACRO
  461. mov ah,0
  462. int 01ah
  463. mov ax,cx ; high word of count
  464. shl eax,16
  465. mov ax,dx ; low word of count
  466. push eax
  467. RE_ENABLE_PAGING_MACRO
  468. pop eax
  469. EXPORT_EXIT_MACRO
  470. ;++
  471. ;
  472. ; Routine Name:
  473. ;
  474. ; Reboot
  475. ;
  476. ; Description:
  477. ;
  478. ; Switches to real-mode and transfers control to a loaded boot sector
  479. ;
  480. ; Arguments:
  481. ;
  482. ; unsigned BootType
  483. ; 0 = FAT. Just jump to 0:7c00.
  484. ; 1 = HPFS. Assumes boot code and super+spare areas (20 sectors)
  485. ; are already loaded at 0xd000; jumps to d00:200.
  486. ; 2 = NTFS. Assumes boot code is loaded (16 sectors) at 0xd000.
  487. ; Jumps to d00:256.
  488. ;
  489. ; Returns:
  490. ; Does not return
  491. ;
  492. ; Environment:
  493. ;
  494. ; Boot sector has been loaded at 7C00
  495. ;--
  496. EXPORT_ENTRY_MACRO Reboot
  497. ;
  498. ; Move the arguments from the caller's 32bit stack to the SU module's
  499. ; 16bit stack.
  500. ;
  501. MAKE_STACK_FRAME_MACRO <RebootFrame>, ebx
  502. ;
  503. ; Go into real mode.
  504. ;
  505. ENTER_REALMODE_MACRO
  506. ;
  507. ; Get the BootType argument. Arguments on realmode stack
  508. ; Make (bp) point to the bottom of the argument frame.
  509. ;
  510. push bp
  511. mov bp,sp
  512. add bp,2
  513. mov edx, [bp].BootType
  514. ;
  515. ; Zero out the firmware heaps, 3000:0000 - 4000:ffff.
  516. ;
  517. xor eax,eax ; prepare for stosd
  518. mov bx,3000h
  519. mov es,bx
  520. mov di,ax ; es:di = physical address 30000
  521. mov cx,4000h ; cx = rep count, # dwords in 64K
  522. cld
  523. rep stosd
  524. mov cx,4000h ; rep count
  525. mov es,cx ; es:di = physical address 40000
  526. rep stosd
  527. ;
  528. ; Disable the A20 line. Some things (like EMM386 and OS/2 on PS/2 machines)
  529. ; hiccup or die if we don't do this.
  530. ;
  531. extrn _DisableA20:near
  532. call _DisableA20
  533. ;
  534. ; Put the video adapter back in 80x25 mode
  535. ;
  536. push dx
  537. mov ax, 0003h
  538. int 010h
  539. pop dx
  540. ;
  541. ; Reset all the segment registers and setup the original stack
  542. ;
  543. mov ax,0
  544. mov ds,ax
  545. mov es,ax
  546. mov fs,ax
  547. mov gs,ax
  548. mov ax,30
  549. mov ss,ax
  550. mov esp,0100h
  551. mov ebp,0
  552. mov esi,0
  553. mov edi,0
  554. test dx,-1
  555. jz FatBoot
  556. ;
  557. ; Setup the registers the way the second sector of the OS/2 HPFS boot code
  558. ; expects them. We skip the first sector entirely, as that just loads in
  559. ; the rest of the sectors. Since the rest of the sectors are ours and not
  560. ; OS/2's, this would cause great distress.
  561. ;
  562. mov ax,07c0h
  563. mov ds, ax
  564. mov ax, 0d00h
  565. mov es, ax
  566. cli
  567. xor ax,ax
  568. mov ss,ax
  569. mov sp, 07c00h
  570. sti
  571. push 0d00h
  572. push 0256h
  573. jmp RebootDoit
  574. FatBoot:
  575. push 0 ; set up for branch to boot sector
  576. push 07c00h
  577. mov dx,080h
  578. ;
  579. ; And away we go!
  580. ;
  581. RebootDoit:
  582. retf
  583. RE_ENABLE_PAGING_MACRO
  584. REMOVE_STACK_FRAME_MACRO <RebootFrame>
  585. EXPORT_EXIT_MACRO
  586. ;++
  587. ;
  588. ; Name:
  589. ;
  590. ; HardwareCursor
  591. ;
  592. ; Description:
  593. ;
  594. ; Positions the hardware cursor and performs other display stuff.
  595. ;
  596. ; Arguments:
  597. ;
  598. ; ULONG Y coord (0 based)
  599. ; ULONG X coord (0 based)
  600. ; TOS -> ULONG Flat return address (must be used with KeCodeSelector)
  601. ;
  602. ; If X = 0x80000000, then Y contains values that get placed into
  603. ; ax (low word of Y) and bx (hi word of y).
  604. ; Otherwise X,Y = coors for cursor
  605. ;
  606. ;
  607. ;--
  608. EXPORT_ENTRY_MACRO HardwareCursor
  609. ;
  610. ; Move the arguments from the caller's 32bit stack to the SU module's
  611. ; 16bit stack.
  612. ;
  613. MAKE_STACK_FRAME_MACRO <HardwareCursorFrame>, ebx
  614. ;
  615. ; Go into real mode. We still have the same stack and sp
  616. ; but we'll be executing in realmode.
  617. ;
  618. ENTER_REALMODE_MACRO
  619. ;
  620. ; Get the requested sectors. Arguments on realmode stack
  621. ; Make (bp) point to the bottom of the argument frame.
  622. ;
  623. push bp
  624. mov bp,sp
  625. add bp,2
  626. ;
  627. ; Put the row (y coord) in dh and the column (x coord) in dl.
  628. ;
  629. mov eax,[bp].YCoord
  630. mov edx,[bp].XCoord
  631. cmp edx,80000000h
  632. jne gotxy
  633. mov ebx,eax
  634. shr ebx,16
  635. jmp doint10
  636. gotxy:
  637. mov dh,al
  638. mov ah,2
  639. mov bh,0
  640. doint10:
  641. int 10h
  642. ;
  643. ; Restore bp and remove stack-frame from stack
  644. ;
  645. pop bp
  646. REMOVE_STACK_FRAME_MACRO <HardwareCursorFrame>
  647. ;
  648. ; Re-enable protect-mode and paging.
  649. ;
  650. RE_ENABLE_PAGING_MACRO
  651. ;
  652. ; Return to caller and the 32bit universe.
  653. ;
  654. EXPORT_EXIT_MACRO
  655. ;++
  656. ;
  657. ; Name:
  658. ;
  659. ; GetDateTime
  660. ;
  661. ; Description:
  662. ;
  663. ; Gets date and time
  664. ;
  665. ; Arguments:
  666. ;
  667. ; ULONG Virtual address of a dword in which to place time.
  668. ; ULONG Virtual address of a dword in which to place date.
  669. ; TOS -> ULONG Flat return address (must be used with KeCodeSelector)
  670. ;
  671. ;--
  672. BCD_TO_BIN macro
  673. xor ah,ah
  674. rol ax,4
  675. ror al,4
  676. aad
  677. endm
  678. EXPORT_ENTRY_MACRO GetDateTime
  679. ;
  680. ; Move the arguments from the caller's 32bit stack to the SU module's
  681. ; 16bit stack.
  682. ;
  683. MAKE_STACK_FRAME_MACRO <GetDateTimeFrame>, ebx
  684. ;
  685. ; Go into real mode. We still have the same stack and sp
  686. ; but we'll be executing in realmode.
  687. ;
  688. ENTER_REALMODE_MACRO
  689. ;
  690. ; Make (bp) point to the bottom of the argument frame.
  691. ;
  692. push bp
  693. mov bp,sp
  694. add bp,2
  695. ;
  696. ; Get the time
  697. ;
  698. mov ah,2
  699. int 1ah
  700. ;
  701. ; Convert BIOS time format into our format and place in caller's dword
  702. ; bits 0-5 are the second
  703. ; bits 6-11 are the minute
  704. ; bits 12-16 are the hour
  705. ;
  706. xor eax,eax
  707. mov al,dh ; BCD seconds
  708. BCD_TO_BIN
  709. movzx edx,ax
  710. mov al,cl ; BCD minutes
  711. BCD_TO_BIN
  712. shl ax,6
  713. or dx,ax
  714. mov al,ch ; BCD hours
  715. BCD_TO_BIN
  716. shl eax,12
  717. or edx,eax
  718. mov eax,[bp].TimeDword
  719. mov bx,ax
  720. and bx,0fh
  721. shr eax,4
  722. mov es,ax
  723. mov es:[bx],edx
  724. ;
  725. ; Get the date
  726. ;
  727. mov ah,4
  728. int 1ah
  729. ;
  730. ; Convert BIOS date format into our format and place in caller's dword
  731. ; bits 0-4 are the day
  732. ; bits 5-8 are the month
  733. ; bits 9-31 are the year
  734. ;
  735. xor eax,eax
  736. mov al,dl ; BCD day
  737. BCD_TO_BIN
  738. mov bl,dh
  739. movzx edx,ax
  740. mov al,bl ; BCD month
  741. BCD_TO_BIN
  742. shl ax,5
  743. or dx,ax
  744. mov al,cl ; BCD year
  745. BCD_TO_BIN
  746. mov cl,al
  747. mov al,ch ; BCD century
  748. BCD_TO_BIN
  749. mov ah,100
  750. mul ah
  751. xor ch,ch
  752. add ax,cx
  753. shl eax,9
  754. or edx,eax
  755. mov eax,[bp].DateDword
  756. mov bx,ax
  757. and bx,0fh
  758. shr eax,4
  759. mov es,ax
  760. mov es:[bx],edx
  761. ;
  762. ; Restore bp and remove stack-frame from stack
  763. ;
  764. pop bp
  765. REMOVE_STACK_FRAME_MACRO <GetDateTimeFrame>
  766. ;
  767. ; Re-enable protect-mode and paging.
  768. ;
  769. RE_ENABLE_PAGING_MACRO
  770. ;
  771. ; Return to caller and the 32bit universe.
  772. ;
  773. EXPORT_EXIT_MACRO
  774. ;++
  775. ;
  776. ; VOID
  777. ; DetectHardware (
  778. ; IN PDETECTION_RECORD DetectionRecord
  779. ; )
  780. ;
  781. ; Routine Description:
  782. ;
  783. ; This routine invokes x86 16 bit real mode detection code from
  784. ; osloader 32 bit flat mode.
  785. ;
  786. ; Arguments:
  787. ;
  788. ; DetectionRecord - Supplies a pointer to a detection record structure.
  789. ;
  790. ; Return Value:
  791. ;
  792. ; None.
  793. ;
  794. ;--
  795. EXPORT_ENTRY_MACRO DetectHardware
  796. ;
  797. ; Move the arguments from the caller's 32bit stack to the SU module's
  798. ; 16bit stack.
  799. ;
  800. MAKE_STACK_FRAME_MACRO <DetectionFrame>, ebx
  801. ;
  802. ; Go into real mode. We still have the same stack and sp
  803. ; but we'll be executing in realmode.
  804. ;
  805. ENTER_REALMODE_MACRO
  806. ;
  807. ; Call the Hardware Detection code
  808. ;
  809. push cs
  810. push offset _TEXT:DetectionDone ; push far return addr
  811. push DETECTION_ADDRESS_SEG
  812. push DETECTION_ADDRESS_OFFSET
  813. retf
  814. DetectionDone:
  815. ;
  816. ; Restore bp and remove stack-frame from stack
  817. ;
  818. REMOVE_STACK_FRAME_MACRO <DetectionFrame>
  819. ;
  820. ; No return code, so we don't save return code around page enabling code
  821. ; Re-enable protect-mode and paging.
  822. ;
  823. RE_ENABLE_PAGING_MACRO
  824. ;
  825. ; Return to caller and the 32bit universe.
  826. ;
  827. EXPORT_EXIT_MACRO
  828. ;++
  829. ;
  830. ; VOID
  831. ; ComPort (
  832. ; IN LONG Port,
  833. ; IN ULONG Function,
  834. ; IN UCHAR Arg
  835. ; )
  836. ;
  837. ; Routine Description:
  838. ;
  839. ; Invoke int14 on com1.
  840. ;
  841. ; Arguments:
  842. ;
  843. ; Port - port # (0 = com1, etc).
  844. ;
  845. ; Function - int 14 function (for ah)
  846. ;
  847. ; Arg - arg for function (for al)
  848. ;
  849. ; Return Value:
  850. ;
  851. ; None.
  852. ;
  853. ;--
  854. EXPORT_ENTRY_MACRO ComPort
  855. ;
  856. ; Move the arguments from the caller's 32bit stack to the SU module's
  857. ; 16bit stack.
  858. ;
  859. MAKE_STACK_FRAME_MACRO <ComPortFrame>, ebx
  860. ;
  861. ; Go into real mode. We still have the same stack and sp
  862. ; but we'll be executing in realmode.
  863. ;
  864. ENTER_REALMODE_MACRO
  865. ;
  866. ; Make (bp) point to the bottom of the argument frame.
  867. ;
  868. push bp
  869. mov bp,sp
  870. add bp,2
  871. ;
  872. ; Get args and call int14
  873. ;
  874. mov ah,byte ptr [bp].ComPortFunction
  875. mov al,byte ptr [bp].ComPortArg
  876. mov dx,word ptr [bp].ComPortPort
  877. int 14h
  878. ;
  879. ; Restore bp and remove stack-frame from stack
  880. ;
  881. pop bp
  882. REMOVE_STACK_FRAME_MACRO <ComPortFrame>
  883. ;
  884. ; No return code, so we don't save return code around page enabling code
  885. ; Re-enable protect-mode and paging.
  886. ;
  887. RE_ENABLE_PAGING_MACRO
  888. ;
  889. ; Return to caller and the 32bit universe.
  890. ;
  891. EXPORT_EXIT_MACRO
  892. ;++
  893. ;
  894. ; ULONG
  895. ; GetStallCount (
  896. ; VOID
  897. ; )
  898. ;
  899. ; Routine Description:
  900. ;
  901. ; Calculates how many increments are required to stall for one microsecond
  902. ;
  903. ; The way this routine works is to set up an ISR on the BIOS vector 1C.
  904. ; This routine will get called 18.2 times a second. The location where
  905. ; IP will be stored when the interrupt occurs is computed and stashed in
  906. ; the code segment. When the ISR fires, the IP on the stack is changed
  907. ; to point to the next chunk of code to execute. So we can spin in a
  908. ; very tight loop and automatically get blown out of the loop when the
  909. ; interrupt occurs.
  910. ;
  911. ; This is all pretty sleazy, but it allows us to calibrate accurately
  912. ; without relying on the 8259 or 8254 (just BIOS). It also does not
  913. ; depend on whether the ISR can affect the CPU registers or not. (some
  914. ; BIOSes, notably Olivetti, will preserve the registers for you)
  915. ;
  916. ; Arguments:
  917. ;
  918. ; None.
  919. ;
  920. ; Return Value:
  921. ;
  922. ; Number of increments required to stall for one microsecond
  923. ;
  924. ;--
  925. EXPORT_ENTRY_MACRO GetStallCount
  926. ;
  927. ; Go into real mode.
  928. ;
  929. ENTER_REALMODE_MACRO
  930. cli
  931. push di
  932. push si
  933. push ds
  934. mov ax,0
  935. mov ds,ax
  936. ;
  937. ; save previous vector
  938. ;
  939. mov di, 01ch*4
  940. mov cx, [di]
  941. mov dx, [di+2]
  942. ;
  943. ; insert our vector
  944. ;
  945. mov ax, offset GscISR
  946. mov [di], ax
  947. push cs
  948. pop ax
  949. mov [di+2], ax
  950. mov eax,0
  951. mov ebx,0
  952. mov si,sp
  953. sub si,6
  954. mov cs:savesp,si
  955. mov cs:newip,offset GscLoop2
  956. sti
  957. ;
  958. ; wait for first tick.
  959. ;
  960. GscLoop1:
  961. cmp ebx,0
  962. je GscLoop1
  963. ;
  964. ; start counting
  965. ;
  966. ;
  967. ; We spin in this loop until the ISR fires. The ISR will munge the return
  968. ; address on the stack to blow us out of the loop and into GscLoop3
  969. ;
  970. GscLoop2:
  971. mov cs:newip,offset GscLoop4
  972. GscLoop3:
  973. add eax,1
  974. jnz short GscLoop3
  975. ;
  976. GscLoop4:
  977. ;
  978. ; stop counting
  979. ;
  980. ;
  981. ; replace old vector
  982. ;
  983. cli
  984. mov [di],cx
  985. mov [di+2],dx
  986. sti
  987. pop ds
  988. pop si
  989. pop di
  990. jmp GscDone
  991. newip dw ?
  992. savesp dw ?
  993. GscISR:
  994. ;
  995. ; blow out of loop
  996. ;
  997. push bp
  998. push ax
  999. mov bp,cs:savesp
  1000. mov ax,cs:newip
  1001. mov ss:[bp],ax
  1002. pop ax
  1003. pop bp
  1004. GscISRdone:
  1005. iret
  1006. GscDone:
  1007. mov edx, eax
  1008. mov ecx,16
  1009. shr edx,cl ; (dx:ax) = dividend
  1010. mov cx,0D6A6h ; (cx) = divisor
  1011. div cx
  1012. and eax,0ffffh
  1013. inc eax ; round loopcount up (prevent 0)
  1014. ;
  1015. ; Re-enable protect-mode and paging.
  1016. ;
  1017. push eax
  1018. RE_ENABLE_PAGING_MACRO
  1019. pop eax
  1020. ;
  1021. ; Return to caller and the 32bit universe.
  1022. ;
  1023. EXPORT_EXIT_MACRO
  1024. ;++
  1025. ;
  1026. ; Routine Name:
  1027. ;
  1028. ; InitializeDisplayForNt
  1029. ;
  1030. ; Description:
  1031. ;
  1032. ; Puts the display into 50 line mode
  1033. ;
  1034. ; Arguments:
  1035. ;
  1036. ; None
  1037. ;
  1038. ; Returns:
  1039. ;
  1040. ; None
  1041. ;
  1042. ;--
  1043. EXPORT_ENTRY_MACRO InitializeDisplayForNt
  1044. ;
  1045. ; Go into real mode.
  1046. ;
  1047. ENTER_REALMODE_MACRO
  1048. mov ax, 1112h ; Load 8x8 font
  1049. mov bx, 0
  1050. int 10h
  1051. RE_ENABLE_PAGING_MACRO
  1052. EXPORT_EXIT_MACRO
  1053. ;++
  1054. ;
  1055. ; Routine Name:
  1056. ;
  1057. ; GetMemoryDescriptor
  1058. ;
  1059. ; Description:
  1060. ;
  1061. ; Returns a memory descriptor
  1062. ;
  1063. ; Arguments:
  1064. ;
  1065. ; pointer to MemoryDescriptorFrame
  1066. ;
  1067. ; Returns:
  1068. ;
  1069. ; None
  1070. ;
  1071. ;--
  1072. EXPORT_ENTRY_MACRO GetMemoryDescriptor
  1073. ;
  1074. ; Move the arguments from the caller's 32bit stack to the SU module's
  1075. ; 16bit stack.
  1076. ;
  1077. MAKE_STACK_FRAME_MACRO <MemoryDescriptorFramePointer>, ebx
  1078. ;
  1079. ; Go into real mode. We still have the same stack and sp
  1080. ; but we'll be executing in realmode.
  1081. ;
  1082. ENTER_REALMODE_MACRO
  1083. ;
  1084. ; Make (bp) point to the bottom of the argument frame.
  1085. ;
  1086. push bp
  1087. mov bp,sp
  1088. add bp,2
  1089. mov eax,[bp].E820FramePointer
  1090. mov bp,ax
  1091. and bp,0fh
  1092. shr eax,4
  1093. mov es,ax ; (es:bp) = E820 Frame
  1094. mov ebx, es:[bp].Key
  1095. mov ecx, es:[bp].DescSize
  1096. lea di, [bp].BaseAddrLow
  1097. mov eax, 0E820h
  1098. mov edx, 'SMAP' ; (edx) = signature
  1099. INT 15h
  1100. mov es:[bp].Key, ebx ; update callers ebx
  1101. mov es:[bp].DescSize, ecx ; update callers size
  1102. sbb ecx, ecx ; ecx = -1 if carry, else 0
  1103. sub eax, 'SMAP' ; eax = 0 if signature matched
  1104. or ecx, eax
  1105. mov es:[bp].ErrorFlag, ecx ; return 0 or non-zero
  1106. ;
  1107. ; Restore bp and remove stack-frame from stack
  1108. ;
  1109. pop bp
  1110. REMOVE_STACK_FRAME_MACRO <MemoryDescriptorFramePointer>
  1111. RE_ENABLE_PAGING_MACRO
  1112. EXPORT_EXIT_MACRO
  1113. ;++
  1114. ;
  1115. ; Routine Name:
  1116. ;
  1117. ; GetElToritoStatus
  1118. ;
  1119. ; Description:
  1120. ;
  1121. ; Get El Torito Disk Emulation Status
  1122. ;
  1123. ; Arguments:
  1124. ;
  1125. ; None
  1126. ;
  1127. ; Returns:
  1128. ;
  1129. ; None
  1130. ;
  1131. ;--
  1132. EXPORT_ENTRY_MACRO GetElToritoStatus
  1133. ;
  1134. ; Move the arguments from the caller's 32bit stack to the SU module's
  1135. ; 16bit stack.
  1136. ;
  1137. MAKE_STACK_FRAME_MACRO <GetElToritoStatusFrame>, ebx
  1138. ;
  1139. ; Go into real mode. We still have the same stack and sp
  1140. ; but we'll be executing in realmode.
  1141. ;
  1142. ENTER_REALMODE_MACRO
  1143. ;
  1144. ; Make (bp) point to the bottom of the argument frame.
  1145. ;
  1146. push bp
  1147. mov bp,sp
  1148. add bp,2
  1149. push dx
  1150. push bx
  1151. push ds
  1152. push si
  1153. ;
  1154. ; Put the Specification Packet pointer into DS:SI, and the Drive
  1155. ; Number on DL. Note that and buffer
  1156. ; addresses passed to this routine MUST be in the lower one
  1157. ; megabyte of memory to be addressable in real mode.
  1158. ;
  1159. mov eax,[bp].SpecPacketPointer
  1160. mov bx,ax
  1161. and bx,0fh
  1162. mov si,bx
  1163. shr eax,4
  1164. mov ds,ax
  1165. mov dl,byte ptr [bp].ETDriveNum
  1166. mov ax,04B01h ; Function = Return Disk Emulation status
  1167. int BIOS_DISK_INTERRUPT
  1168. jc etstatuserr
  1169. ;
  1170. ; Carry wasn't set so we have no error and need to "clean" eax of
  1171. ; any garbage that may have been left in it.
  1172. ;
  1173. xor eax,eax
  1174. etstatuserr:
  1175. ;
  1176. ; Mask-off any garbage that my have been left in the upper
  1177. ; 16bits of eax.
  1178. ;
  1179. and eax,0000ffffh
  1180. pop si
  1181. pop ds
  1182. pop bx
  1183. pop dx
  1184. ;
  1185. ; Restore bp and remove stack-frame from stack
  1186. ;
  1187. pop bp
  1188. REMOVE_STACK_FRAME_MACRO <GetElToritoStatusFrame>
  1189. ;
  1190. ; Save return code on 16bit stack
  1191. ; Re-enable protect-mode and paging.
  1192. ;
  1193. push eax
  1194. RE_ENABLE_PAGING_MACRO
  1195. pop eax
  1196. ;
  1197. ; Return to caller and the 32bit universe.
  1198. ;
  1199. EXPORT_EXIT_MACRO
  1200. ;++
  1201. ;
  1202. ; Routine Name:
  1203. ;
  1204. ; GetExtendedInt13Params
  1205. ;
  1206. ; Description:
  1207. ;
  1208. ; Determine if extended int13 services are available for a drive
  1209. ; and if so retrieve extended disk parameters.
  1210. ;
  1211. ; Arguments:
  1212. ;
  1213. ; - 32-bit flat pointer to 26-byte param packet filled by this routine
  1214. ;
  1215. ; - int 13 unit number
  1216. ;
  1217. ; Returns:
  1218. ;
  1219. ; ax = 0 means extended int13 not supported on the given drive
  1220. ; ax = 1 means extended int13 supported and param packet filled in
  1221. ;
  1222. ;--
  1223. EXPORT_ENTRY_MACRO GetExtendedInt13Params
  1224. ;
  1225. ; Move the arguments from the caller's 32bit stack to the SU module's
  1226. ; 16bit stack.
  1227. ;
  1228. MAKE_STACK_FRAME_MACRO <GetExtendedInt13ParamsFrame>, ebx
  1229. ;
  1230. ; Go into real mode. We still have the same stack and sp
  1231. ; but we'll be executing in realmode.
  1232. ;
  1233. ENTER_REALMODE_MACRO
  1234. ;
  1235. ; Make (bp) point to the bottom of the argument frame.
  1236. ;
  1237. push bp
  1238. mov bp,sp
  1239. add bp,2
  1240. push dx
  1241. push bx
  1242. push ds
  1243. push si
  1244. ;
  1245. ; Check for support for this drive.
  1246. ;
  1247. mov ah,41h
  1248. mov bx,55aah
  1249. mov dl,byte ptr [bp].Int13UnitNumber
  1250. int BIOS_DISK_INTERRUPT
  1251. jc noxint13 ; carry set means no xint13
  1252. cmp bx,0aa55h ; check signature
  1253. jnz noxint13 ; not present, no xint13
  1254. test cl,1 ; bit 0 clear means no xint13
  1255. jz noxint13
  1256. ;
  1257. ; If we get here it looks like we have xint13 support.
  1258. ; Some BIOSes are broken though so we do some validation while we're
  1259. ; asking for the extended int13 drive parameters for the drive.
  1260. ; Note that and buffer addresses passed to this routine
  1261. ; MUST be in the lower one megabyte of memory to be addressable in real mode.
  1262. ;
  1263. mov eax,[bp].ParamPacketPointer
  1264. mov bx,ax
  1265. and bx,0fh
  1266. mov si,bx
  1267. shr eax,4
  1268. mov ds,ax ; DS:SI -> param packet
  1269. mov word ptr [si],26 ; initialize packet with size
  1270. ; some bioses helpfully zero out
  1271. ; the whole buffer according to
  1272. ; this size, so make SURE the
  1273. ; entire word is initialized and
  1274. ; there's no junk in the high byte.
  1275. mov dl,byte ptr [bp].Int13UnitNumber
  1276. mov ah,48h
  1277. int BIOS_DISK_INTERRUPT
  1278. jc noxint13
  1279. ;
  1280. ; If we get here then everything's cool and we have xint13 parameters.
  1281. ; We also know carry isn't set.
  1282. ;
  1283. mov al,1
  1284. jnc xint13done
  1285. noxint13:
  1286. xor al,al
  1287. xint13done:
  1288. movzx eax,al
  1289. pop si
  1290. pop ds
  1291. pop bx
  1292. pop dx
  1293. ;
  1294. ; Restore bp and remove stack-frame from stack
  1295. ;
  1296. pop bp
  1297. REMOVE_STACK_FRAME_MACRO <GetExtendedInt13ParamsFrame>
  1298. ;
  1299. ; Save return code on 16bit stack
  1300. ; Re-enable protect-mode and paging.
  1301. ;
  1302. push eax
  1303. RE_ENABLE_PAGING_MACRO
  1304. pop eax
  1305. ;
  1306. ; Return to caller and the 32bit universe.
  1307. ;
  1308. EXPORT_EXIT_MACRO
  1309. ;++
  1310. ;
  1311. ; Routine Name:
  1312. ;
  1313. ; ApmAttemptReconnect
  1314. ;
  1315. ; Description:
  1316. ;
  1317. ; Called only during x86 resume from hiberate operation. Attempts
  1318. ; to connect to APM bios in same way ntdetect.com did on first try,
  1319. ; so that if APM is present on the machine, it will be reinited to
  1320. ; the same working state it was in before hibernate.
  1321. ;
  1322. ; APM version, addresses, selector mappings, etc, are assumed
  1323. ; not to have changed while the machine is hibernated.
  1324. ;
  1325. ;
  1326. ; Arguments:
  1327. ;
  1328. ; None.
  1329. ;
  1330. ; Returns:
  1331. ;
  1332. ; None. (It either works or it doesn't.)
  1333. ;
  1334. ;--
  1335. ;
  1336. ; Yet another set of cheater APM include values
  1337. ;
  1338. APM_INSTALLATION_CHECK equ 5300h
  1339. APM_REAL_MODE_CONNECT equ 5301h
  1340. APM_PROTECT_MODE_16bit_CONNECT equ 5302h
  1341. APM_DRIVER_VERSION equ 530Eh
  1342. APM_DISCONNECT equ 5304h
  1343. APM_DEVICE_BIOS equ 0h
  1344. APM_MODE_16BIT equ 1h
  1345. EXPORT_ENTRY_MACRO ApmAttemptReconnect
  1346. ;
  1347. ; Go into real mode. We still have the same stack and sp
  1348. ; but we'll be executing in realmode.
  1349. ;
  1350. ENTER_REALMODE_MACRO
  1351. ;
  1352. ; APM installation check
  1353. ;
  1354. mov eax,APM_INSTALLATION_CHECK
  1355. mov ebx,APM_DEVICE_BIOS
  1356. int 15h
  1357. jc aar_punt
  1358. cmp bl,'M'
  1359. jnz aar_punt
  1360. cmp bh,'P'
  1361. jnz aar_punt
  1362. ;
  1363. ; If we get here, we have an APM bios. If we just call it,
  1364. ; we may get grief. So we will connect in real mode, then
  1365. ; set our version to the whatever the driver says it is, or 1.2,
  1366. ; whichever is LESS. Then query options again.
  1367. ;
  1368. cmp ah,1
  1369. jle aar10
  1370. mov ah,1 ; ah = min(old ah, 1)
  1371. aar10:
  1372. cmp al,2
  1373. jle aar20
  1374. mov al,2 ; al = min(old al, 2)
  1375. aar20:
  1376. ;
  1377. ; ax = min(apm version, 1.2)
  1378. ;
  1379. push ax
  1380. ;
  1381. ; connect to the real mode interface
  1382. ;
  1383. mov ax,APM_REAL_MODE_CONNECT
  1384. mov bx,APM_DEVICE_BIOS
  1385. int 15h
  1386. pop ax
  1387. jc aar_punt
  1388. push ax
  1389. ;
  1390. ; set the version of the real mode interface
  1391. ;
  1392. mov cx,ax ; ax = major.minor
  1393. mov bx,APM_DEVICE_BIOS
  1394. mov ax,APM_DRIVER_VERSION
  1395. int 15h
  1396. pop ax
  1397. jc aar_punt
  1398. ;
  1399. ; do the install check again, now that we've connected and
  1400. ; set the version to min(apm ver, 1.2) some apm bios code
  1401. ; will give us different install parameters now.
  1402. ;
  1403. mov ax,APM_INSTALLATION_CHECK
  1404. mov bx,APM_DEVICE_BIOS
  1405. int 15h
  1406. jc aar_punt
  1407. ;
  1408. ; If we are here:
  1409. ; AH = revised Major version
  1410. ; AL = revised Minor version
  1411. ; CX = APM Flags
  1412. ;
  1413. push cx
  1414. push ax
  1415. ;
  1416. ; Now disconnect from the real mode interface
  1417. ;
  1418. mov ax,APM_DISCONNECT
  1419. mov bx,APM_DEVICE_BIOS
  1420. int 15h
  1421. pop ax
  1422. pop cx
  1423. jc aar_punt
  1424. ;
  1425. ; Since we are here:
  1426. ; AH = revised Major version
  1427. ; AL = revised Minor version
  1428. ; CX = apm parameters
  1429. ;
  1430. ; APM is present, and seems to work, and we've set it to the
  1431. ; version number that we think it and we both like.
  1432. ;
  1433. ; So, things should just work, if APM has proper support
  1434. ; for the modes and features that we need.
  1435. ;
  1436. cmp cx,APM_MODE_16BIT
  1437. jz aar_punt
  1438. ;
  1439. ; 16bit protected mode is available
  1440. ;
  1441. push ax
  1442. push cx
  1443. ;
  1444. ; do 16 bit protected mode connect
  1445. ;
  1446. mov ax,APM_PROTECT_MODE_16bit_CONNECT
  1447. mov bx,APM_DEVICE_BIOS
  1448. int 15h
  1449. pop cx
  1450. pop ax
  1451. jc aar_punt
  1452. ;
  1453. ; do 16 bit protected mode set version
  1454. ;
  1455. mov cx,ax
  1456. mov ax,APM_DRIVER_VERSION
  1457. mov bx,APM_DEVICE_BIOS
  1458. int 15h
  1459. ;
  1460. ; if NC, then we have connect to 16bit proected mode interface,
  1461. ; AND set the version. since ntdetect.com presumably did this
  1462. ; exact same thing at first boot, we already have GDT entries pointing
  1463. ; to the 16bit code, hooks set, etc. So, in theory, it just works.
  1464. ;
  1465. ; if CY here, or anywhere above, APM doesn't work for us. Too bad.
  1466. ;
  1467. aar_punt:
  1468. ;
  1469. ; return to paged mode
  1470. ;
  1471. RE_ENABLE_PAGING_MACRO
  1472. ;
  1473. ; Return to caller and the 32bit universe.
  1474. ;
  1475. EXPORT_EXIT_MACRO
  1476. _TEXT ends
  1477. end