Source code of Windows XP (NT5)
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.

722 lines
17 KiB

  1. title "Abios Support Assembly Routines"
  2. ;++
  3. ;
  4. ; Copyright (c) 1989 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; abiosa.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements assembley code for ABIOS support.
  13. ;
  14. ; Author:
  15. ;
  16. ; Shie-Lin Tzong (shielint) 25-May-1991
  17. ;
  18. ; Environment:
  19. ;
  20. ; Kernel mode only.
  21. ;
  22. ; Revision History:
  23. ;
  24. ;--
  25. .386p
  26. .xlist
  27. include ks386.inc
  28. include callconv.inc ; calling convention macros
  29. include i386\kimacro.inc
  30. .list
  31. extrn _DbgPrint:proc
  32. EXTRNP _KeRaiseIrql,2,IMPORT
  33. EXTRNP _KeLowerIrql,1,IMPORT
  34. EXTRNP _KeGetCurrentIrql,0,IMPORT
  35. extrn _KiStack16GdtEntry:DWORD
  36. ;
  37. ; This should be either 0 or 1, if it's greater than 1, then we've re-entered the BIOS.
  38. ;
  39. extrn _KiInBiosCall:DWORD
  40. extrn _FlagState:DWORD
  41. extrn _KiBiosFrame:DWORD
  42. OPERAND_OVERRIDE equ 66h
  43. ADDRESS_OVERRIDE equ 67h
  44. KGDT_CDA16 equ 0E8h
  45. LocalStack equ 16 ; 4 DWORDS of slop for PnPBioses.
  46. if DBG
  47. extrn KiBiosReenteredAssert:DWORD
  48. endif
  49. ; Macro change note:
  50. ;
  51. ; This macro pair used to do an uncondtional sti coming back from the 16-bit
  52. ; side, this potentially caused problems in APM. Now we save and restore the
  53. ; flag state
  54. ;
  55. ;++
  56. ;
  57. ; STACK32_TO_STACK16
  58. ;
  59. ; Macro Description:
  60. ;
  61. ; This macro remaps current 32bit stack to 16bit stack.
  62. ;
  63. ; Arguments:
  64. ;
  65. ; None.
  66. ;
  67. ;--
  68. STACK32_TO_STACK16 macro
  69. pushfd
  70. mov ecx,[esp]
  71. mov _FlagState,ecx
  72. popfd
  73. mov eax, fs:PcStackLimit ; [eax] = 16-bit stack selector base
  74. mov edx, eax
  75. mov ecx, _KiStack16GdtEntry
  76. mov word ptr [ecx].KgdtBaseLow, ax
  77. shr eax, 16
  78. mov byte ptr [ecx].KgdtBaseMid, al
  79. mov byte ptr [ecx].KgdtBaseHi, ah
  80. mov eax, esp
  81. sub eax, edx
  82. cli
  83. mov esp, eax
  84. mov eax, KGDT_STACK16
  85. mov ss, ax
  86. ;
  87. ; NOTE that we MUST leave interrupts remain off.
  88. ; We'll turn it back on after we switch to 16 bit code.
  89. ;
  90. endm
  91. ;++
  92. ;
  93. ; STACK16_TO_STACK32
  94. ;
  95. ; Macro Description:
  96. ;
  97. ; This macro remaps current 32bit stack to 16bit stack.
  98. ;
  99. ; Arguments:
  100. ;
  101. ; None.
  102. ;
  103. ;--
  104. STACK16_TO_STACK32 macro Stack32
  105. db OPERAND_OVERRIDE
  106. mov eax, esp
  107. db OPERAND_OVERRIDE
  108. db ADDRESS_OVERRIDE
  109. add eax, fs:PcStackLimit
  110. cli
  111. db OPERAND_OVERRIDE
  112. mov esp, eax
  113. db OPERAND_OVERRIDE
  114. mov eax, KGDT_R0_DATA
  115. mov ss, ax
  116. db OPERAND_OVERRIDE
  117. db ADDRESS_OVERRIDE
  118. push ds:_FlagState
  119. db OPERAND_OVERRIDE
  120. popfd
  121. endm
  122. COPY_CALL_FRAME macro FramePtr
  123. mov [FramePtr].TsEax,eax
  124. mov [FramePtr].TsEbx,ebx
  125. mov [FramePtr].TsEcx,ecx
  126. mov [FramePtr].TsEdx,edx
  127. mov [FramePtr].TsEsi,esi
  128. mov [FramePtr].TsEdi,edi
  129. mov [FramePtr].TsEbp,ebp
  130. mov [FramePtr].TsHardwareEsp,esp
  131. mov [FramePtr].TsSegFs,fs
  132. mov [FramePtr].TsSegCs,cs
  133. endm
  134. page ,132
  135. subttl "Abios Support Code"
  136. _TEXT SEGMENT DWORD PUBLIC 'CODE'
  137. ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
  138. ;
  139. ; BBT cannot instrument code between this label and BBT_Exclude_Selector_Code_End
  140. ;
  141. public _BBT_Exclude_Selector_Code_Begin
  142. _BBT_Exclude_Selector_Code_Begin equ $
  143. int 3
  144. ;++
  145. ; ULONG
  146. ; KiAbiosGetGdt (
  147. ; VOID
  148. ; )
  149. ;
  150. ; Routine Description:
  151. ;
  152. ; This routine returns the starting address of GDT of current processor.
  153. ;
  154. ; Arguments:
  155. ;
  156. ; None.
  157. ;
  158. ; Return Value:
  159. ;
  160. ; return Pcr->GDT
  161. ;
  162. ;--
  163. cPublicProc _KiAbiosGetGdt,0
  164. mov eax, fs:PcGdt
  165. stdRET _KiAbiosGetGdt
  166. stdENDP _KiAbiosGetGdt
  167. ;++
  168. ; VOID
  169. ; KiI386CallAbios(
  170. ; IN KABIOS_POINTER AbiosFunction,
  171. ; IN KABIOS_POINTER DeviceBlockPointer,
  172. ; IN KABIOS_POINTER FunctionTransferTable,
  173. ; IN KABIOS_POINTER RequestBlock
  174. ; )
  175. ;
  176. ; Routine Description:
  177. ;
  178. ; This function invokes ABIOS service function for device driver. This
  179. ; routine is executing at DIAPTCH_LEVEL to prevent context swapping.
  180. ;
  181. ; N.B. We arrive here from the Ke386AbiosCall with a 32bit CS. That is,
  182. ; we're executing the code with cs:eip where cs contains a selector for a
  183. ; 32bit flat segment. We want to get to a 16bit cs. That is, cs:ip.
  184. ; The reason is that ABIOS is running at 16 bit segment.
  185. ; Before we can call ABIOS service we must load ss and cs segment
  186. ; registers with selectors for 16bit segments. We start by pushing a far
  187. ; pointer to a label in the macro and then doing a retf. This allows us
  188. ; to fall through to the next instruction, but we're now executing
  189. ; through cs:ip with a 16bit CS. Then, we remap our 32-bit stack to 16-bit
  190. ; stack.
  191. ;
  192. ; Arguments:
  193. ;
  194. ; AbiosFunction - a 16:16 pointer to the abios service function.
  195. ;
  196. ; DeviceBlockPointer - a 16:16 pointer to Device Block.
  197. ;
  198. ; FunctionTransferTable - a 16:16 pointer to Function Transfer Table.
  199. ;
  200. ; RequestBlock - a 16:16 pointer to device driver's request block.
  201. ;
  202. ; Return Value:
  203. ;
  204. ; None.
  205. ;--
  206. KacAbiosFunction equ [ebp + 8]
  207. KacDeviceBlock equ [ebp + 12]
  208. KacFunctionTable equ [ebp + 16]
  209. KacRequestBlock equ [ebp + 20]
  210. cPublicProc _KiI386CallAbios,4
  211. ;
  212. ; We're using a 32bit CS:EIP - go to a 16bit CS:IP
  213. ; Note the base of KiAbiosCallSelector is the flat address of _KiI386AbiosCall
  214. ; routine.
  215. ;
  216. push ebp
  217. mov ebp, esp
  218. push ebx
  219. COPY_CALL_FRAME _KiBiosFrame
  220. sub esp,LocalStack ; After C style frame
  221. stdCall _KeGetCurrentIrql
  222. push eax ; Local Varible
  223. cmp al, DISPATCH_LEVEL ; Is irql > Dispatch_level?
  224. jae short Kac00
  225. ; Raise to Dispatch Level
  226. mov eax, esp
  227. stdCall _KeRaiseIrql, <DISPATCH_LEVEL,eax>
  228. Kac00:
  229. ;
  230. ; Set up parameters on stack before remapping stack.
  231. ;
  232. push word ptr KGDT_CDA16 ; CDA anchor selector
  233. push KacRequestBlock ; Request Block
  234. push KacFunctionTable ; Func transfer table
  235. push KacDeviceBlock ; Device Block
  236. mov ebx, KacAbiosFunction ; (ebx)-> Abios Entry
  237. ;
  238. ; Remap current stack to 16:16 stack. The base of the 16bit stack selector is
  239. ; the base of current kernel stack.
  240. ;
  241. inc _KiInBiosCall ; Set the 'In Bios' flag
  242. if DBG
  243. cmp _KiInBiosCall,2
  244. jb @F
  245. push offset FLAT:KiBiosReenteredAssert
  246. call _dbgPrint
  247. add esp, 4
  248. @@:
  249. endif
  250. STACK32_TO_STACK16 ; Switch to 16bit stack
  251. push word ptr KGDT_CODE16
  252. IFDEF STD_CALL
  253. push word ptr (offset FLAT:Kac40 - offset FLAT:_KiI386CallAbios@16)
  254. push KGDT_CODE16
  255. push offset FLAT:Kac30 - offset FLAT:_KiI386CallAbios@16
  256. ELSE
  257. push word ptr (offset FLAT:Kac40 - offset FLAT:_KiI386CallAbios)
  258. push KGDT_CODE16
  259. push offset FLAT:Kac30 - offset FLAT:_KiI386CallAbios
  260. ENDIF
  261. retf
  262. Kac30:
  263. ;
  264. ; Stack switching (from 32 to 16) turns interrupt off. We must turn it
  265. ; back on.
  266. ;
  267. sti
  268. push bx ; Yes, BX not EBX!
  269. retf
  270. Kac40:
  271. add esp, 14 ; pop out all the parameters
  272. STACK16_TO_STACK32 ; switch back to 32 bit stack
  273. ;
  274. ; Pull callers flat return address off stack and push the
  275. ; flat code selector followed by the return offset, then
  276. ; execute a far return and we'll be back in the 32-bit code space.
  277. ;
  278. db OPERAND_OVERRIDE
  279. push KGDT_R0_CODE
  280. db OPERAND_OVERRIDE
  281. push offset FLAT:Kac50
  282. db OPERAND_OVERRIDE
  283. retf
  284. Kac50:
  285. pop eax ; [eax] = OldIrql
  286. pop ebx ; restore ebx
  287. cmp al, DISPATCH_LEVEL
  288. jae short Kac60
  289. stdCall _KeLowerIrql, <eax> ; Lower irql to original level
  290. Kac60:
  291. dec _KiInBiosCall ;Clear 'In Bios' Flag
  292. add esp,LocalStack ; subtract off the scratch space
  293. pop ebp
  294. stdRET _KiI386CallAbios
  295. stdENDP _KiI386CallAbios
  296. ;; ********************************************************
  297. ;;
  298. ;; BEGIN - power_management
  299. ;;
  300. ;;
  301. ;++
  302. ; VOID
  303. ; KeI386Call16BitFunction (
  304. ; IN OUT PCONTEXT Regs
  305. ; )
  306. ;
  307. ; Routine Description:
  308. ;
  309. ; This function calls the 16 bit function specified in the Regs.
  310. ;
  311. ; Parameters:
  312. ;
  313. ; Regs - supplies a pointer to register context to call 16 function.
  314. ;
  315. ; NOTE: Caller must be at DPC_LEVEL
  316. ;
  317. ;--
  318. cPublicProc _KeI386Call16BitFunction,1
  319. ; verify CurrentIrql
  320. ; verify context flags
  321. push ebp ; save nonvolatile registers
  322. push ebx
  323. push esi
  324. push edi
  325. mov ebx, dword ptr [esp + 20] ; (ebx)-> Context
  326. COPY_CALL_FRAME _KiBiosFrame
  327. sub esp,LocalStack ; After prolog
  328. inc _KiInBiosCall ; Set the 'In Bios' flag
  329. if DBG
  330. cmp _KiInBiosCall,2
  331. jb @F
  332. push offset FLAT:KiBiosReenteredAssert
  333. call _dbgPrint
  334. add esp, 4
  335. @@:
  336. endif
  337. ;
  338. ; We're using a 32bit CS:EIP - go to a 16bit CS:IP
  339. ; Note the base of KiAbiosCallSelector is the flat address of _KiI386AbiosCall
  340. ; routine.
  341. ;
  342. ;
  343. ; Remap current stack to 16:16 stack. The base of the 16bit stack selector is
  344. ; the base of current kernel stack.
  345. ;
  346. STACK32_TO_STACK16 ; Switch to 16bit stack
  347. ;
  348. ; Push return address from 16 bit function call to kernel
  349. ;
  350. push word ptr KGDT_CODE16
  351. push word ptr (offset FLAT:Kbf40 - offset FLAT:_KiI386CallAbios@16)
  352. ;
  353. ; Load context to call with
  354. ;
  355. push word ptr [ebx].CsEFlags
  356. push word ptr [ebx].CsSegCs
  357. push word ptr [ebx].CsEip
  358. mov eax, [ebx].CsEax
  359. mov ecx, [ebx].CsEcx
  360. mov edx, [ebx].CsEdx
  361. mov edi, [ebx].CsEdi
  362. mov esi, [ebx].CsEsi
  363. mov ebp, [ebx].CsEbp
  364. push [ebx].CsSegGs
  365. push [ebx].CsSegFs
  366. push [ebx].CsSegEs
  367. push [ebx].CsSegDs
  368. mov ebx, [ebx].CsEbx
  369. pop ds
  370. pop es
  371. pop fs
  372. pop gs
  373. ;
  374. ; Switch to 16bit CS
  375. ;
  376. push KGDT_CODE16
  377. push offset FLAT:Kbf30 - offset FLAT:_KiI386CallAbios@16
  378. retf
  379. Kbf30:
  380. ;
  381. ; "call" to 16 bit function
  382. ;
  383. iretd
  384. Kbf40:
  385. ;
  386. ; Push some of the returned context which will be needed to
  387. ; switch back to the 32 bit SS & CS.
  388. ;
  389. db OPERAND_OVERRIDE
  390. push ds
  391. db OPERAND_OVERRIDE
  392. push es
  393. db OPERAND_OVERRIDE
  394. push fs
  395. db OPERAND_OVERRIDE
  396. push gs
  397. db OPERAND_OVERRIDE
  398. push eax
  399. db OPERAND_OVERRIDE
  400. pushfd
  401. db OPERAND_OVERRIDE
  402. mov eax, KGDT_R0_PCR
  403. mov fs, ax
  404. db OPERAND_OVERRIDE
  405. mov eax, KGDT_R3_DATA OR RPL_MASK
  406. mov ds, ax
  407. mov es, ax
  408. xor eax, eax
  409. ;
  410. ; Switch back to 32 bit stack
  411. ;
  412. STACK16_TO_STACK32
  413. ;
  414. ; Push the flat code selector followed by the return offset, then
  415. ; execute a far return and we'll be back in the 32-bit code space.
  416. ;
  417. db OPERAND_OVERRIDE
  418. push KGDT_R0_CODE
  419. db OPERAND_OVERRIDE
  420. push offset FLAT:Kbf50
  421. db OPERAND_OVERRIDE
  422. retf
  423. Kbf50:
  424. ;
  425. ; Return resulting context
  426. ;
  427. mov eax, dword ptr [esp+44+LocalStack] ; (eax) = Context Record
  428. pop [eax].CsEflags
  429. pop [eax].CsEax
  430. pop [eax].CsSegGs
  431. pop [eax].CsSegFs
  432. pop [eax].CsSegEs
  433. pop [eax].CsSegDs
  434. mov [eax].CsEbx, ebx
  435. mov [eax].CsEcx, ecx
  436. mov [eax].CsEdx, edx
  437. mov [eax].CsEdi, edi
  438. mov [eax].CsEsi, esi
  439. mov [eax].CsEbp, ebp
  440. ;
  441. ; Restore regs & return
  442. ;
  443. dec _KiInBiosCall ; Clear the 'In Bios' flag
  444. add esp,LocalStack ;remove scratch space
  445. pop edi
  446. pop esi
  447. pop ebx
  448. pop ebp
  449. stdRET _KeI386Call16BitFunction
  450. stdENDP _KeI386Call16BitFunction
  451. ;++
  452. ; USHORT
  453. ; KeI386Call16BitCStyleFunction (
  454. ; IN ULONG EntryOffset,
  455. ; IN ULONG EntrySelector,
  456. ; IN PUCHAR Parameters,
  457. ; IN ULONG Size
  458. ; )
  459. ;
  460. ; Routine Description:
  461. ;
  462. ; This function calls the 16 bit function which supports C style calling convension.
  463. ;
  464. ; Parameters:
  465. ;
  466. ; EntryOffset and EntrySelector - specifies the entry point of the 16 bit function.
  467. ;
  468. ; Parameters - supplies a pointer to a parameter block which will be
  469. ; passed to 16 bit function as parameters.
  470. ;
  471. ; Size - supplies the size of the parameter block.
  472. ;
  473. ; NOTE: Caller must be at DPC_LEVEL
  474. ;
  475. ; Returned Value:
  476. ;
  477. ; AX returned by 16 bit function.
  478. ;
  479. ;--
  480. cPublicProc _KeI386Call16BitCStyleFunction,4
  481. ;
  482. ; verify CurrentIrql
  483. ; verify context flags
  484. ;
  485. push ebp ; save nonvolatile registers
  486. push ebx
  487. push esi
  488. push edi
  489. COPY_CALL_FRAME _KiBiosFrame
  490. inc _KiInBiosCall ; Set the 'In Bios' flag
  491. if DBG
  492. cmp _KiInBiosCall,2
  493. jb @F
  494. push offset FLAT:KiBiosReenteredAssert
  495. call _dbgPrint
  496. add esp, 4
  497. @@:
  498. endif
  499. mov edi, esp
  500. sub esp,LocalStack ; now, add in some scratch space
  501. mov esi, dword ptr [esp + LocalStack +28] ; (esi)->BiosParameters
  502. or esi, esi
  503. jz short @f
  504. mov ecx, [esp + LocalStack +32] ; (ecx) = parameter size
  505. sub esp, ecx ; allocate space on TOS to copy parameters
  506. mov edi, esp
  507. rep movsb ; (edi)-> Top of nonvolatile reg save area
  508. add edi, LocalStack ; edi now points to original stack
  509. @@:
  510. ;
  511. ; We're using a 32bit CS:EIP - go to a 16bit CS:IP
  512. ; Note the base of KiAbiosCallSelector is the flat address of _KiI386AbiosCall
  513. ; routine.
  514. ;
  515. ;
  516. ; Remap current stack to 16:16 stack. The base of the 16bit stack selector is
  517. ; the base of current kernel stack.
  518. ;
  519. STACK32_TO_STACK16 ; Switch to 16bit stack
  520. ;
  521. ; Push return address from 16 bit function call to kernel
  522. ;
  523. push word ptr KGDT_CODE16
  524. push word ptr (offset FLAT:Kbfex40 - offset FLAT:_KiI386CallAbios@16)
  525. push word ptr 0200h ; flags
  526. push word ptr [edi + 24 ] ; entry selector
  527. push word ptr [edi + 20 ] ; entry offset
  528. ;
  529. ; Switch to 16bit CS
  530. ;
  531. push KGDT_CODE16
  532. push offset FLAT:Kbfex30 - offset FLAT:_KiI386CallAbios@16
  533. retf
  534. Kbfex30:
  535. ;
  536. ; "call" to 16 bit function
  537. ;
  538. iretd
  539. Kbfex40:
  540. ;
  541. ; Save return value.
  542. ;
  543. db OPERAND_OVERRIDE
  544. push eax
  545. ;
  546. ; Restore Flat mode segment registers.
  547. ;
  548. db OPERAND_OVERRIDE
  549. mov eax, KGDT_R0_PCR
  550. mov fs, ax
  551. db OPERAND_OVERRIDE
  552. mov eax, KGDT_R3_DATA OR RPL_MASK
  553. mov ds, ax
  554. mov es, ax
  555. xor eax, eax
  556. ;
  557. ; Switch back to 32 bit stack
  558. ;
  559. STACK16_TO_STACK32
  560. ;
  561. ; Push the flat code selector followed by the return offset, then
  562. ; execute a far return and we'll be back in the 32-bit code space.
  563. ;
  564. db OPERAND_OVERRIDE
  565. push KGDT_R0_CODE
  566. db OPERAND_OVERRIDE
  567. push offset FLAT:Kbfex50
  568. db OPERAND_OVERRIDE
  569. retf
  570. Kbfex50:
  571. pop eax
  572. ;
  573. ; Restore regs & return
  574. ;
  575. dec _KiInBiosCall ; Clear the 'In Bios' flag
  576. mov esp, edi ; Also removes the scratch space!
  577. pop edi
  578. pop esi
  579. pop ebx
  580. pop ebp
  581. stdRET _KeI386Call16BitCStyleFunction
  582. stdENDP _KeI386Call16BitCStyleFunction
  583. ;
  584. ; BBT cannot instrument code between BBT_Exclude_Selector_Code_Begin and this label
  585. ;
  586. public _BBT_Exclude_Selector_Code_End
  587. _BBT_Exclude_Selector_Code_End equ $
  588. int 3
  589. ;;
  590. ;; END - power_management
  591. ;;
  592. ;; ********************************************************
  593. public _KiEndOfCode16
  594. _KiEndOfCode16 equ $
  595. _TEXT ends
  596. end