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.

762 lines
20 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. abiosc.c
  5. Abstract:
  6. This module implements ABIOS support C routines for i386 NT.
  7. Author:
  8. Shie-Lin Tzong (shielint) 20-May-1991
  9. Environment:
  10. Boot loader privileged, FLAT mode.
  11. Revision History:
  12. --*/
  13. #include "ki.h"
  14. #pragma hdrstop
  15. #include "abios.h"
  16. extern PKCOMMON_DATA_AREA KiCommonDataArea;
  17. extern BOOLEAN KiAbiosPresent;
  18. //
  19. // The reason of having these variables defined in here is to isolate
  20. // ABIOS from current system.
  21. //
  22. //
  23. // KiNumberFreeSelectors defines the number of available selectors for
  24. // ABIOS specific drivers. This number should be the same accross all
  25. // the processors.
  26. //
  27. static USHORT KiNumberFreeSelectors = 0;
  28. //
  29. // KiFreeGdtListHead points to the head of free GDT list on the processor 0.
  30. //
  31. static PKFREE_GDT_ENTRY KiFreeGdtListHead = 0L;
  32. //
  33. // Logica Id Table to control the ownership of logical Id.
  34. //
  35. PKLID_TABLE_ENTRY KiLogicalIdTable;
  36. //
  37. // KiAbiosGdt[] defines the Starting address of GDT for each processor.
  38. //
  39. ULONG KiAbiosGdt[MAXIMUM_PROCESSORS];
  40. //
  41. // SpinLock for accessing GDTs
  42. //
  43. KSPIN_LOCK KiAbiosGdtLock;
  44. //
  45. // Spinlock for accessing Logical Id Table
  46. //
  47. KSPIN_LOCK KiAbiosLidTableLock;
  48. //
  49. // KiStack16GdtEntry defines the address of the gdt entry for 16 bit stack.
  50. //
  51. ULONG KiStack16GdtEntry;
  52. VOID
  53. KiInitializeAbiosGdtEntry (
  54. OUT PKGDTENTRY GdtEntry,
  55. IN ULONG Base,
  56. IN ULONG Limit,
  57. IN USHORT Type
  58. )
  59. /*++
  60. Routine Description:
  61. This function initializes a GDT entry for abios specific code. Base,
  62. Limit, and Type (code, data) are set according to parameters. All other
  63. fields of the entry are set to match standard system values.
  64. N.B. The BIG and GRANULARITY are always set to 0.
  65. Arguments:
  66. GdtEntry - GDT descriptor to be filled in.
  67. Base - Linear address of the first byte mapped by the selector.
  68. Limit - Size of the selector in BYTE.
  69. Type - Code or Data. All code selectors are marked readable,
  70. all data selectors are marked writeable.
  71. Return Value:
  72. Pointer to the GDT entry.
  73. --*/
  74. {
  75. GdtEntry->LimitLow = (USHORT)(Limit & 0xffff);
  76. GdtEntry->BaseLow = (USHORT)(Base & 0xffff);
  77. GdtEntry->HighWord.Bytes.BaseMid = (UCHAR)((Base & 0xff0000) >> 16);
  78. GdtEntry->HighWord.Bits.Type = Type;
  79. GdtEntry->HighWord.Bits.Dpl = 0;
  80. GdtEntry->HighWord.Bits.Pres = 1;
  81. GdtEntry->HighWord.Bits.LimitHi = (Limit & 0xf0000) >> 16;
  82. GdtEntry->HighWord.Bits.Sys = 0;
  83. GdtEntry->HighWord.Bits.Reserved_0 = 0;
  84. GdtEntry->HighWord.Bits.Default_Big = 0;
  85. GdtEntry->HighWord.Bits.Granularity = 0;
  86. GdtEntry->HighWord.Bytes.BaseHi = (UCHAR)((Base & 0xff000000) >> 24);
  87. }
  88. ULONG
  89. KiI386SelectorBase (
  90. IN USHORT Selector
  91. )
  92. /*++
  93. Routine Description:
  94. This function returns the base address of the specified GDT selector.
  95. Arguments:
  96. Selector - Supplies the desired selector.
  97. Return Value:
  98. SelectorBase - Return the base address of the specified selector;
  99. (return -1L if invalid selector)
  100. --*/
  101. {
  102. PKGDTENTRY GdtEntry;
  103. GdtEntry = (PKGDTENTRY)(KiAbiosGetGdt() + Selector);
  104. if (GdtEntry->HighWord.Bits.Pres) {
  105. return ((ULONG)GdtEntry->BaseLow |
  106. (ULONG)GdtEntry->HighWord.Bytes.BaseMid << 16 |
  107. (ULONG)GdtEntry->HighWord.Bytes.BaseHi << 24);
  108. } else {
  109. return (ULONG)(-1L);
  110. }
  111. }
  112. NTSTATUS
  113. KeI386GetLid(
  114. IN USHORT DeviceId,
  115. IN USHORT RelativeLid,
  116. IN BOOLEAN SharedLid,
  117. IN PDRIVER_OBJECT DriverObject,
  118. OUT PUSHORT LogicalId
  119. )
  120. /*++
  121. Routine Description:
  122. This function searches Device Blocks and Common Data Area for the
  123. Logical Id matching the specified Device Id.
  124. N.B. (WARNING shielint) To speed the search, this routine ASSUMES that
  125. the LIDs with the same Device ID always appear consecutively in the
  126. Common Data Area. IBM ABIOS doc does not explicitly specify this.
  127. But from the way ABIOS initializes Device Block and Function Transfer
  128. Table, I think the assumption is true.
  129. Arguments:
  130. DeviceId - Desired Device Id.
  131. RelativeLid - Specifies the Nth logical Id for this device Id. A value
  132. of 0 indicates the first available Lid.
  133. SharedLid - A boolean value indicates if it is a shared or exclusively
  134. owned logical Id.
  135. DriverObject - Supplies a 32-bit flat pointer of the requesting device
  136. driver's driver object. The DriverObject is used to establish
  137. the ownership of the desired LID.
  138. LogicalId - A pointer to a variable which will receive the Lid.
  139. Return Value:
  140. STATUS_SUCCESS - If the requested LID is available.
  141. STATUS_ABIOS_NOT_PRESENT - If there is no ABIOS support in the system.
  142. STATUS_ABIOS_LID_NOT_EXIST - If the specified LID does not exist.
  143. STATUS_ABIOS_LID_ALREADY_OWNED - If the caller requests an exclusively
  144. owned LID.
  145. --*/
  146. {
  147. PKDB_FTT_SECTION CdaPointer;
  148. PKDEVICE_BLOCK DeviceBlock;
  149. USHORT Lid, RelativeLidCount = 1;
  150. ULONG Owner;
  151. USHORT Increment;
  152. KIRQL OldIrql;
  153. NTSTATUS Status;
  154. if (!KiAbiosPresent) {
  155. return STATUS_ABIOS_NOT_PRESENT;
  156. }
  157. if (SharedLid) {
  158. Owner = LID_NO_SPECIFIC_OWNER;
  159. Increment = 1;
  160. } else {
  161. Owner = (ULONG)DriverObject;
  162. Increment = 0;
  163. }
  164. //
  165. // If the Logical Id Table hasn't been created yet, create it now.
  166. //
  167. if (KiLogicalIdTable==NULL) {
  168. KiLogicalIdTable = ExAllocatePoolWithTag(NonPagedPool,
  169. NUMBER_LID_TABLE_ENTRIES *
  170. sizeof(KLID_TABLE_ENTRY),
  171. ' eK');
  172. if (KiLogicalIdTable == NULL) {
  173. return(STATUS_NO_MEMORY);
  174. }
  175. RtlZeroMemory(KiLogicalIdTable, NUMBER_LID_TABLE_ENTRIES*sizeof(KLID_TABLE_ENTRY));
  176. }
  177. //
  178. // For each Lid defined in Common Data Area, we check if it has non
  179. // empty device block and function transfer table. If yes, we proceed
  180. // to check the device id. Otherwise, we skip the Lid.
  181. //
  182. CdaPointer = (PKDB_FTT_SECTION)KiCommonDataArea + 2;
  183. Status = STATUS_ABIOS_LID_NOT_EXIST;
  184. ExAcquireSpinLock(&KiAbiosLidTableLock, &OldIrql);
  185. for (Lid = 2; Lid < KiCommonDataArea->NumberLids; Lid++) {
  186. if (CdaPointer->DeviceBlock.Selector != 0 &&
  187. CdaPointer->FunctionTransferTable.Selector != 0) {
  188. DeviceBlock = (PKDEVICE_BLOCK)(KiI386SelectorBase(
  189. CdaPointer->DeviceBlock.Selector)
  190. + (CdaPointer->DeviceBlock.Offset));
  191. if (DeviceBlock->DeviceId == DeviceId) {
  192. if (RelativeLid == RelativeLidCount || RelativeLid == 0) {
  193. if (KiLogicalIdTable[Lid].Owner == 0L) {
  194. KiLogicalIdTable[Lid].Owner = Owner;
  195. KiLogicalIdTable[Lid].OwnerCount += Increment;
  196. *LogicalId = Lid;
  197. Status = STATUS_SUCCESS;
  198. } else if (KiLogicalIdTable[Lid].Owner == LID_NO_SPECIFIC_OWNER) {
  199. if (SharedLid) {
  200. *LogicalId = Lid;
  201. KiLogicalIdTable[Lid].OwnerCount += Increment;
  202. Status = STATUS_SUCCESS;
  203. } else {
  204. Status = STATUS_ABIOS_LID_ALREADY_OWNED;
  205. }
  206. } else if (KiLogicalIdTable[Lid].Owner == (ULONG)DriverObject) {
  207. *LogicalId = Lid;
  208. Status = STATUS_SUCCESS;
  209. } else if (RelativeLid != 0) {
  210. Status = STATUS_ABIOS_LID_ALREADY_OWNED;
  211. }
  212. break;
  213. } else {
  214. RelativeLidCount++;
  215. }
  216. }
  217. }
  218. CdaPointer++;
  219. }
  220. ExReleaseSpinLock(&KiAbiosLidTableLock, OldIrql);
  221. return Status;
  222. }
  223. NTSTATUS
  224. KeI386ReleaseLid(
  225. IN USHORT LogicalId,
  226. IN PDRIVER_OBJECT DriverObject
  227. )
  228. /*++
  229. Routine Description:
  230. This function releases a logical Id. This routine is called at ABIOS
  231. device driver destallation or termination.
  232. Arguments:
  233. LogicalId - Logical Id to be released.
  234. DriverObject - Supplies a 32-bit flat pointer of the requesting device
  235. driver's driver object. The DriverObject is used to check
  236. the ownership of the specified LID.
  237. Return Value:
  238. STATUS_SUCCESS - If the requested LID is released.
  239. STATUS_ABIOS_NOT_PRESENT - If there is no ABIOS support in the system.
  240. STATUS_ABIOS_NOT_LID_OWNER - If the caller does not own the LID.
  241. --*/
  242. {
  243. KIRQL OldIrql;
  244. NTSTATUS Status;
  245. if (!KiAbiosPresent) {
  246. return STATUS_ABIOS_NOT_PRESENT;
  247. }
  248. ExAcquireSpinLock(&KiAbiosLidTableLock, &OldIrql);
  249. if (KiLogicalIdTable[LogicalId].Owner == (ULONG)DriverObject) {
  250. KiLogicalIdTable[LogicalId].Owner = 0L;
  251. Status = STATUS_SUCCESS;
  252. } else if (KiLogicalIdTable[LogicalId].Owner == LID_NO_SPECIFIC_OWNER) {
  253. KiLogicalIdTable[LogicalId].OwnerCount--;
  254. if (KiLogicalIdTable[LogicalId].OwnerCount == 0L) {
  255. KiLogicalIdTable[LogicalId].Owner = 0L;
  256. }
  257. Status = STATUS_SUCCESS;
  258. } else {
  259. Status = STATUS_ABIOS_NOT_LID_OWNER;
  260. }
  261. ExReleaseSpinLock(&KiAbiosLidTableLock, OldIrql);
  262. return Status;
  263. }
  264. NTSTATUS
  265. KeI386AbiosCall(
  266. IN USHORT LogicalId,
  267. IN PDRIVER_OBJECT DriverObject,
  268. IN PUCHAR RequestBlock,
  269. IN USHORT EntryPoint
  270. )
  271. /*++
  272. Routine Description:
  273. This function calls an ABIOS service routine on behave of device driver
  274. using Operating System Transfer Convension.
  275. Arguments:
  276. LogicalId - Logical Id for the call.
  277. DriverObject - Supplies a 32-bit flat pointer of the requesting device
  278. driver's driver object. The DriverObject is used to verify
  279. the ownership of the desired LID.
  280. RequestBlock - A 16:16 (selector:offset) pointer to the request block.
  281. EntryPoint - Specifies which ABIOS entry point:
  282. 0 - Start Routine
  283. 1 - Interrupt Routine
  284. 2 - Timeout Routine
  285. Return Value:
  286. STATUS_SUCCESS - If no error.
  287. STATUS_ABIOS_NOT_PRESENT - If there is no ABIOS support in the system.
  288. STATUS_ABIOS_INVALID_COMMAND - if the specified entry point is not supported.
  289. STATUS_ABIOS_INVALID_LID - If the Lid specified is invalid.
  290. STATUS_ABIOS_NOT_LID_OWNER - If the caller does not own this Lid.
  291. (Note that the request specific ABIOS returned code is in RequestBlock.)
  292. --*/
  293. {
  294. KABIOS_POINTER FuncTransferTable;
  295. KABIOS_POINTER DeviceBlock;
  296. KABIOS_POINTER AbiosFunction;
  297. PKFUNCTION_TRANSFER_TABLE FttPointer;
  298. if (!KiAbiosPresent) {
  299. return STATUS_ABIOS_NOT_PRESENT;
  300. }
  301. if (LogicalId >= KiCommonDataArea->NumberLids) {
  302. return STATUS_ABIOS_INVALID_LID;
  303. } else if (KiLogicalIdTable[LogicalId].Owner != (ULONG)DriverObject &&
  304. KiLogicalIdTable[LogicalId].Owner != LID_NO_SPECIFIC_OWNER) {
  305. return STATUS_ABIOS_NOT_LID_OWNER;
  306. } else if (EntryPoint > 2) {
  307. return STATUS_ABIOS_INVALID_COMMAND;
  308. }
  309. FuncTransferTable = ((PKDB_FTT_SECTION)KiCommonDataArea + LogicalId)->
  310. FunctionTransferTable;
  311. DeviceBlock = ((PKDB_FTT_SECTION)KiCommonDataArea + LogicalId)->DeviceBlock;
  312. FttPointer = (PKFUNCTION_TRANSFER_TABLE)(KiI386SelectorBase(FuncTransferTable.Selector) +
  313. (ULONG)FuncTransferTable.Offset);
  314. AbiosFunction = FttPointer->CommonRoutine[EntryPoint];
  315. KiI386CallAbios(AbiosFunction,
  316. DeviceBlock,
  317. FuncTransferTable,
  318. *(PKABIOS_POINTER)&RequestBlock
  319. );
  320. return STATUS_SUCCESS;
  321. }
  322. NTSTATUS
  323. KeI386AllocateGdtSelectors(
  324. OUT PUSHORT SelectorArray,
  325. IN USHORT NumberOfSelectors
  326. )
  327. /*++
  328. Routine Description:
  329. This function allocates a set of GDT selectors for a device driver to use.
  330. Usually this allocation is performed at device driver initialization time
  331. to reserve the selectors for later use.
  332. Arguments:
  333. SelectorArray - Supplies a pointer to an array of USHORT to be filled
  334. in with the GDT selectors allocated.
  335. NumberOfSelectors - Specifies the number of selectors to be allocated.
  336. Return Value:
  337. STATUS_SUCCESS - If the requested selectors are allocated.
  338. STATUS_ABIOS_SELECTOR_NOT_AVAILABLE - if systen can not allocate the number
  339. of selectors requested.
  340. --*/
  341. {
  342. PKFREE_GDT_ENTRY GdtEntry;
  343. KIRQL OldIrql;
  344. if (KiNumberFreeSelectors >= NumberOfSelectors) {
  345. ExAcquireSpinLock(&KiAbiosGdtLock, &OldIrql);
  346. //
  347. // The Free Gdt link list is maintained on Processor 0's GDT ONLY.
  348. // Because the 'selector' is an offset to the beginning of GDT and
  349. // it should be the same accross all the processors.
  350. //
  351. KiNumberFreeSelectors -= NumberOfSelectors;
  352. GdtEntry = KiFreeGdtListHead;
  353. while (NumberOfSelectors != 0) {
  354. *SelectorArray++ = (USHORT)((ULONG)GdtEntry - KiAbiosGdt[0]);
  355. GdtEntry = GdtEntry->Flink;
  356. NumberOfSelectors--;
  357. }
  358. KiFreeGdtListHead = GdtEntry;
  359. ExReleaseSpinLock(&KiAbiosGdtLock, OldIrql);
  360. return STATUS_SUCCESS;
  361. } else {
  362. return STATUS_ABIOS_SELECTOR_NOT_AVAILABLE;
  363. }
  364. }
  365. NTSTATUS
  366. KeI386ReleaseGdtSelectors(
  367. OUT PUSHORT SelectorArray,
  368. IN USHORT NumberOfSelectors
  369. )
  370. /*++
  371. Routine Description:
  372. This function releases a set of GDT selectors for a device driver.
  373. Usually this function is called at device driver termination or
  374. deinstallation time.
  375. Arguments:
  376. SelectorArray - Supplies a pointer to an array of USHORT selectors
  377. to be freed.
  378. NumberOfSelectors - Specifies the number of selectors to be released.
  379. Return Value:
  380. STATUS_SUCCESS - If the requested LID is released.
  381. --*/
  382. {
  383. PKFREE_GDT_ENTRY GdtEntry;
  384. KIRQL OldIrql;
  385. ULONG Gdt;
  386. ExAcquireSpinLock(&KiAbiosGdtLock, &OldIrql);
  387. //
  388. // The Free Gdt link list is maintained on Processor 0's GDT ONLY.
  389. // Because the 'selector' is an offset to the beginning of GDT and
  390. // it should be the same accross all the processors.
  391. //
  392. KiNumberFreeSelectors += NumberOfSelectors;
  393. Gdt = KiAbiosGdt[0];
  394. while (NumberOfSelectors != 0) {
  395. GdtEntry = (PKFREE_GDT_ENTRY)(Gdt + *SelectorArray++);
  396. GdtEntry->Flink = KiFreeGdtListHead;
  397. KiFreeGdtListHead = GdtEntry;
  398. NumberOfSelectors--;
  399. }
  400. ExReleaseSpinLock(&KiAbiosGdtLock, OldIrql);
  401. return STATUS_SUCCESS;
  402. }
  403. NTSTATUS
  404. KeI386FlatToGdtSelector(
  405. IN ULONG SelectorBase,
  406. IN USHORT Length,
  407. IN USHORT Selector
  408. )
  409. /*++
  410. Routine Description:
  411. This function converts a 32-bit flat address to a GDT selector-offset
  412. pair. The segment set up is always 16-bit ring 0 data segment.
  413. Arguments:
  414. SelectorBase - Supplies 32 bit flat address to be set as the base address
  415. of the desired selector.
  416. Length - Supplies the Length of the segment. The Length is a 16 bit value
  417. and zero means 64KB.
  418. Selector - Supplies the selector to be set up.
  419. Return Value:
  420. STATUS_SUCCESS - If the requested LID is released.
  421. STATUS_ABIOS_NOT_PRESENT - If there is no ABIOS support in the system.
  422. STATUS_ABIOS_INVALID_SELECTOR - If the selector supplied is invalid.
  423. --*/
  424. {
  425. PKGDTENTRY GdtEntry, GdtEntry1;
  426. KIRQL OldIrql;
  427. ULONG i;
  428. if (!KiAbiosPresent) {
  429. return STATUS_ABIOS_NOT_PRESENT;
  430. }
  431. if (Selector < RESERVED_GDT_ENTRIES * sizeof(KGDTENTRY)) {
  432. return STATUS_ABIOS_INVALID_SELECTOR;
  433. } else {
  434. ExAcquireSpinLock(&KiAbiosGdtLock, &OldIrql);
  435. GdtEntry = (PKGDTENTRY)(KiAbiosGdt[0] + Selector);
  436. GdtEntry->LimitLow = (USHORT)(Length - 1);
  437. GdtEntry->BaseLow = LOWWORD(SelectorBase);
  438. GdtEntry->HighWord.Bytes.BaseMid = LOWBYTE(HIGHWORD(SelectorBase));
  439. GdtEntry->HighWord.Bytes.BaseHi = HIGHBYTE(HIGHWORD(SelectorBase));
  440. GdtEntry->HighWord.Bits.Pres = 1;
  441. GdtEntry->HighWord.Bits.Type = TYPE_DATA;
  442. GdtEntry->HighWord.Bits.Dpl = DPL_SYSTEM;
  443. for (i = 1; i < (ULONG)KeNumberProcessors; i++) {
  444. GdtEntry1 = (PKGDTENTRY)(KiAbiosGdt[i] + Selector);
  445. *GdtEntry1 = *GdtEntry;
  446. }
  447. ExReleaseSpinLock(&KiAbiosGdtLock, OldIrql);
  448. return STATUS_SUCCESS;
  449. }
  450. }
  451. VOID
  452. Ki386InitializeGdtFreeList (
  453. PKFREE_GDT_ENTRY EndOfGdt
  454. )
  455. /*++
  456. Routine Description:
  457. This function initializes gdt free list by linking all the unused gdt
  458. entries to a free list.
  459. Arguments:
  460. EndOfGdt - Supplies the ending address of desired GDT.
  461. Return Value:
  462. None.
  463. --*/
  464. {
  465. PKFREE_GDT_ENTRY GdtEntry;
  466. GdtEntry = EndOfGdt - 1;
  467. KiFreeGdtListHead = (PKFREE_GDT_ENTRY)0;
  468. while (GdtEntry != (PKFREE_GDT_ENTRY)KiAbiosGetGdt() +
  469. RESERVED_GDT_ENTRIES - 1) {
  470. if (GdtEntry->Present == 0) {
  471. GdtEntry->Flink = KiFreeGdtListHead;
  472. KiFreeGdtListHead = GdtEntry;
  473. KiNumberFreeSelectors++;
  474. }
  475. GdtEntry--;
  476. }
  477. }
  478. VOID
  479. KiInitializeAbios (
  480. IN UCHAR Processor
  481. )
  482. /*++
  483. Routine Description:
  484. This function initializes gdt free list and sets up selector for
  485. KiI386AbiosCall (16-bit code).
  486. Arguments:
  487. Processor - the processor who performs the initialization.
  488. Return Value:
  489. None.
  490. --*/
  491. {
  492. ULONG GdtLength;
  493. PKGDTENTRY AliasGdtSelectorEntry;
  494. PKFREE_GDT_ENTRY EndOfGdt;
  495. //
  496. // First check if abios is recognized by osloader.
  497. //
  498. KiCommonDataArea = KeLoaderBlock->u.I386.CommonDataArea;
  499. //
  500. // NOTE For now we want to disable ABIOS support on MP.
  501. //
  502. if (KiCommonDataArea == NULL || Processor != 0) {
  503. KiAbiosPresent = FALSE;
  504. } else {
  505. KiAbiosPresent = TRUE;
  506. }
  507. //
  508. // Initialize the spinlocks for accessing GDTs and Lid Table.
  509. //
  510. KeInitializeSpinLock( &KiAbiosGdtLock );
  511. KeInitializeSpinLock( &KiAbiosLidTableLock );
  512. //
  513. // Determine the starting and ending addresses of GDT.
  514. //
  515. KiAbiosGdt[Processor] = KiAbiosGetGdt();
  516. AliasGdtSelectorEntry = (PKGDTENTRY)(KiAbiosGetGdt() + KGDT_GDT_ALIAS);
  517. GdtLength = 1 + (ULONG)(AliasGdtSelectorEntry->LimitLow) +
  518. (ULONG)(AliasGdtSelectorEntry->HighWord.Bits.LimitHi << 16);
  519. EndOfGdt = (PKFREE_GDT_ENTRY)(KiAbiosGetGdt() + GdtLength);
  520. //
  521. // Prepare selector for 16 bit stack segment
  522. //
  523. KiStack16GdtEntry = KiAbiosGetGdt() + KGDT_STACK16;
  524. KiInitializeAbiosGdtEntry(
  525. (PKGDTENTRY)KiStack16GdtEntry,
  526. 0L,
  527. 0xffff,
  528. TYPE_DATA
  529. );
  530. //
  531. // Establish the addressability of Common Data Area selector.
  532. //
  533. KiInitializeAbiosGdtEntry(
  534. (PKGDTENTRY)(KiAbiosGetGdt() + KGDT_CDA16),
  535. (ULONG)KiCommonDataArea,
  536. 0xffff,
  537. TYPE_DATA
  538. );
  539. //
  540. // Set up 16-bit code selector for KiI386AbiosCall
  541. //
  542. KiInitializeAbiosGdtEntry(
  543. (PKGDTENTRY)(KiAbiosGetGdt() + KGDT_CODE16),
  544. (ULONG)&KiI386CallAbios,
  545. (ULONG)&KiEndOfCode16 - (ULONG)&KiI386CallAbios - 1,
  546. 0x18 // TYPE_CODE
  547. );
  548. //
  549. // Link all the unused GDT entries to our GDT free list.
  550. //
  551. if (Processor == 0) {
  552. Ki386InitializeGdtFreeList(EndOfGdt);
  553. }
  554. }