00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
#include "ki.h"
00027
#pragma hdrstop
00028
#include "abios.h"
00029
00030 extern PKCOMMON_DATA_AREA KiCommonDataArea;
00031 extern BOOLEAN
KiAbiosPresent;
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 static USHORT KiNumberFreeSelectors = 0;
00045
00046
00047
00048
00049
00050 static PKFREE_GDT_ENTRY KiFreeGdtListHead = 0
L;
00051
00052
00053
00054
00055
00056 PKLID_TABLE_ENTRY KiLogicalIdTable;
00057
00058
00059
00060
00061
00062 ULONG
KiAbiosGdt[
MAXIMUM_PROCESSORS];
00063
00064
00065
00066
00067
00068 KSPIN_LOCK
KiAbiosGdtLock;
00069
00070
00071
00072
00073
00074 KSPIN_LOCK
KiAbiosLidTableLock;
00075
00076
00077
00078
00079
00080 ULONG
KiStack16GdtEntry;
00081
00082
VOID
00083 KiInitializeAbiosGdtEntry (
00084 OUT PKGDTENTRY GdtEntry,
00085 IN ULONG Base,
00086 IN ULONG Limit,
00087 IN USHORT Type
00088 )
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 {
00118 GdtEntry->LimitLow = (
USHORT)(Limit & 0xffff);
00119 GdtEntry->BaseLow = (
USHORT)(Base & 0xffff);
00120 GdtEntry->HighWord.Bytes.BaseMid = (UCHAR)((Base & 0xff0000) >> 16);
00121 GdtEntry->HighWord.Bits.Type = Type;
00122 GdtEntry->HighWord.Bits.Dpl = 0;
00123 GdtEntry->HighWord.Bits.Pres = 1;
00124 GdtEntry->HighWord.Bits.LimitHi = (Limit & 0xf0000) >> 16;
00125 GdtEntry->HighWord.Bits.Sys = 0;
00126 GdtEntry->HighWord.Bits.Reserved_0 = 0;
00127 GdtEntry->HighWord.Bits.Default_Big = 0;
00128 GdtEntry->HighWord.Bits.Granularity = 0;
00129 GdtEntry->HighWord.Bytes.BaseHi = (UCHAR)((Base & 0xff000000) >> 24);
00130 }
00131
00132 ULONG
00133 KiI386SelectorBase (
00134 IN USHORT Selector
00135 )
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 {
00156 PKGDTENTRY GdtEntry;
00157
00158
00159 GdtEntry = (PKGDTENTRY)(
KiAbiosGetGdt() + Selector);
00160
if (GdtEntry->HighWord.Bits.Pres) {
00161
return ((ULONG)GdtEntry->BaseLow |
00162 (ULONG)GdtEntry->HighWord.Bytes.BaseMid << 16 |
00163 (ULONG)GdtEntry->HighWord.Bytes.BaseHi << 24);
00164 }
else {
00165
return (ULONG)(-1
L);
00166 }
00167 }
00168
00169
NTSTATUS
00170 KeI386GetLid(
00171 IN USHORT DeviceId,
00172 IN USHORT RelativeLid,
00173 IN BOOLEAN SharedLid,
00174 IN
PDRIVER_OBJECT DriverObject,
00175 OUT
PUSHORT LogicalId
00176 )
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 {
00221
PKDB_FTT_SECTION CdaPointer;
00222
PKDEVICE_BLOCK DeviceBlock;
00223
USHORT Lid, RelativeLidCount = 1;
00224 ULONG
Owner;
00225
USHORT Increment;
00226 KIRQL OldIrql;
00227
NTSTATUS Status;
00228
00229
if (!
KiAbiosPresent) {
00230
return STATUS_ABIOS_NOT_PRESENT;
00231 }
00232
00233
if (SharedLid) {
00234
Owner =
LID_NO_SPECIFIC_OWNER;
00235
Increment = 1;
00236 }
else {
00237
Owner = (ULONG)DriverObject;
00238
Increment = 0;
00239 }
00240
00241
00242
00243
00244
if (
KiLogicalIdTable==
NULL) {
00245
KiLogicalIdTable =
ExAllocatePoolWithTag(
NonPagedPool,
00246
NUMBER_LID_TABLE_ENTRIES *
00247
sizeof(
KLID_TABLE_ENTRY),
00248 ' eK');
00249
if (
KiLogicalIdTable ==
NULL) {
00250
return(STATUS_NO_MEMORY);
00251 }
00252 RtlZeroMemory(
KiLogicalIdTable,
NUMBER_LID_TABLE_ENTRIES*
sizeof(
KLID_TABLE_ENTRY));
00253 }
00254
00255
00256
00257
00258
00259
00260
00261 CdaPointer = (
PKDB_FTT_SECTION)
KiCommonDataArea + 2;
00262
Status = STATUS_ABIOS_LID_NOT_EXIST;
00263
00264 ExAcquireSpinLock(&
KiAbiosLidTableLock, &OldIrql);
00265
00266
for (Lid = 2; Lid <
KiCommonDataArea->
NumberLids; Lid++) {
00267
if (CdaPointer->
DeviceBlock.
Selector != 0 &&
00268 CdaPointer->
FunctionTransferTable.
Selector != 0) {
00269
00270 DeviceBlock = (
PKDEVICE_BLOCK)(
KiI386SelectorBase(
00271 CdaPointer->
DeviceBlock.
Selector)
00272 + (CdaPointer->
DeviceBlock.
Offset));
00273
if (DeviceBlock->
DeviceId == DeviceId) {
00274
if (RelativeLid == RelativeLidCount || RelativeLid == 0) {
00275
if (
KiLogicalIdTable[Lid].
Owner == 0
L) {
00276
KiLogicalIdTable[Lid].
Owner =
Owner;
00277
KiLogicalIdTable[Lid].
OwnerCount +=
Increment;
00278 *LogicalId = Lid;
00279
Status = STATUS_SUCCESS;
00280 }
else if (
KiLogicalIdTable[Lid].
Owner ==
LID_NO_SPECIFIC_OWNER) {
00281
if (SharedLid) {
00282 *LogicalId = Lid;
00283
KiLogicalIdTable[Lid].
OwnerCount +=
Increment;
00284
Status = STATUS_SUCCESS;
00285 }
else {
00286
Status = STATUS_ABIOS_LID_ALREADY_OWNED;
00287 }
00288 }
else if (
KiLogicalIdTable[Lid].
Owner == (ULONG)DriverObject) {
00289 *LogicalId = Lid;
00290
Status = STATUS_SUCCESS;
00291 }
else if (RelativeLid != 0) {
00292
Status = STATUS_ABIOS_LID_ALREADY_OWNED;
00293 }
00294
break;
00295 }
else {
00296 RelativeLidCount++;
00297 }
00298 }
00299 }
00300 CdaPointer++;
00301 }
00302
00303 ExReleaseSpinLock(&
KiAbiosLidTableLock, OldIrql);
00304
return Status;
00305 }
00306
00307
NTSTATUS
00308 KeI386ReleaseLid(
00309 IN USHORT LogicalId,
00310 IN
PDRIVER_OBJECT DriverObject
00311 )
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 {
00339 KIRQL OldIrql;
00340
NTSTATUS Status;
00341
00342
if (!
KiAbiosPresent) {
00343
return STATUS_ABIOS_NOT_PRESENT;
00344 }
00345
00346 ExAcquireSpinLock(&
KiAbiosLidTableLock, &OldIrql);
00347
00348
if (
KiLogicalIdTable[LogicalId].
Owner == (ULONG)DriverObject) {
00349
KiLogicalIdTable[LogicalId].
Owner = 0
L;
00350
Status = STATUS_SUCCESS;
00351 }
else if (
KiLogicalIdTable[LogicalId].
Owner ==
LID_NO_SPECIFIC_OWNER) {
00352
KiLogicalIdTable[LogicalId].
OwnerCount--;
00353
if (
KiLogicalIdTable[LogicalId].
OwnerCount == 0
L) {
00354
KiLogicalIdTable[LogicalId].
Owner = 0
L;
00355 }
00356
Status = STATUS_SUCCESS;
00357 }
else {
00358
Status = STATUS_ABIOS_NOT_LID_OWNER;
00359 }
00360
00361 ExReleaseSpinLock(&
KiAbiosLidTableLock, OldIrql);
00362
00363
return Status;
00364 }
00365
00366
NTSTATUS
00367 KeI386AbiosCall(
00368 IN USHORT LogicalId,
00369 IN
PDRIVER_OBJECT DriverObject,
00370 IN PUCHAR RequestBlock,
00371 IN USHORT EntryPoint
00372 )
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 {
00414
00415
KABIOS_POINTER FuncTransferTable;
00416
KABIOS_POINTER DeviceBlock;
00417
KABIOS_POINTER AbiosFunction;
00418
PKFUNCTION_TRANSFER_TABLE FttPointer;
00419
00420
if (!
KiAbiosPresent) {
00421
return STATUS_ABIOS_NOT_PRESENT;
00422 }
00423
00424
if (LogicalId >=
KiCommonDataArea->
NumberLids) {
00425
return STATUS_ABIOS_INVALID_LID;
00426 }
else if (
KiLogicalIdTable[LogicalId].
Owner != (ULONG)DriverObject &&
00427
KiLogicalIdTable[LogicalId].
Owner !=
LID_NO_SPECIFIC_OWNER) {
00428
return STATUS_ABIOS_NOT_LID_OWNER;
00429 }
else if (EntryPoint > 2) {
00430
return STATUS_ABIOS_INVALID_COMMAND;
00431 }
00432
00433 FuncTransferTable = ((
PKDB_FTT_SECTION)
KiCommonDataArea + LogicalId)->
00434 FunctionTransferTable;
00435 DeviceBlock = ((
PKDB_FTT_SECTION)
KiCommonDataArea + LogicalId)->DeviceBlock;
00436 FttPointer = (
PKFUNCTION_TRANSFER_TABLE)(
KiI386SelectorBase(FuncTransferTable.
Selector) +
00437 (ULONG)FuncTransferTable.
Offset);
00438 AbiosFunction = FttPointer->
CommonRoutine[EntryPoint];
00439
KiI386CallAbios(AbiosFunction,
00440 DeviceBlock,
00441 FuncTransferTable,
00442 *(
PKABIOS_POINTER)&RequestBlock
00443 );
00444
00445
return STATUS_SUCCESS;
00446 }
00447
00448
NTSTATUS
00449 KeI386AllocateGdtSelectors(
00450 OUT PUSHORT SelectorArray,
00451 IN USHORT NumberOfSelectors
00452 )
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 {
00479
PKFREE_GDT_ENTRY GdtEntry;
00480 KIRQL OldIrql;
00481
00482
if (
KiNumberFreeSelectors >= NumberOfSelectors) {
00483 ExAcquireSpinLock(&
KiAbiosGdtLock, &OldIrql);
00484
00485
00486
00487
00488
00489
00490
00491
KiNumberFreeSelectors -= NumberOfSelectors;
00492 GdtEntry =
KiFreeGdtListHead;
00493
while (NumberOfSelectors != 0) {
00494 *SelectorArray++ = (
USHORT)((ULONG)GdtEntry -
KiAbiosGdt[0]);
00495 GdtEntry = GdtEntry->
Flink;
00496 NumberOfSelectors--;
00497 }
00498
KiFreeGdtListHead = GdtEntry;
00499 ExReleaseSpinLock(&
KiAbiosGdtLock, OldIrql);
00500
return STATUS_SUCCESS;
00501 }
else {
00502
return STATUS_ABIOS_SELECTOR_NOT_AVAILABLE;
00503 }
00504 }
00505
00506
NTSTATUS
00507 KeI386ReleaseGdtSelectors(
00508 OUT PUSHORT SelectorArray,
00509 IN USHORT NumberOfSelectors
00510 )
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532 {
00533
PKFREE_GDT_ENTRY GdtEntry;
00534 KIRQL OldIrql;
00535 ULONG Gdt;
00536
00537 ExAcquireSpinLock(&
KiAbiosGdtLock, &OldIrql);
00538
00539
00540
00541
00542
00543
00544
00545
KiNumberFreeSelectors += NumberOfSelectors;
00546 Gdt =
KiAbiosGdt[0];
00547
while (NumberOfSelectors != 0) {
00548 GdtEntry = (
PKFREE_GDT_ENTRY)(Gdt + *SelectorArray++);
00549 GdtEntry->
Flink =
KiFreeGdtListHead;
00550
KiFreeGdtListHead = GdtEntry;
00551 NumberOfSelectors--;
00552 }
00553 ExReleaseSpinLock(&
KiAbiosGdtLock, OldIrql);
00554
return STATUS_SUCCESS;
00555 }
00556
00557
NTSTATUS
00558 KeI386FlatToGdtSelector(
00559 IN ULONG SelectorBase,
00560 IN USHORT Length,
00561 IN USHORT Selector
00562 )
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592 {
00593 PKGDTENTRY GdtEntry, GdtEntry1;
00594 KIRQL OldIrql;
00595 ULONG i;
00596
00597
if (!
KiAbiosPresent) {
00598
return STATUS_ABIOS_NOT_PRESENT;
00599 }
00600
if (Selector <
RESERVED_GDT_ENTRIES *
sizeof(KGDTENTRY)) {
00601
return STATUS_ABIOS_INVALID_SELECTOR;
00602 }
else {
00603 ExAcquireSpinLock(&
KiAbiosGdtLock, &OldIrql);
00604 GdtEntry = (PKGDTENTRY)(
KiAbiosGdt[0] + Selector);
00605 GdtEntry->LimitLow = (
USHORT)(Length - 1);
00606 GdtEntry->BaseLow = LOWWORD(SelectorBase);
00607 GdtEntry->HighWord.Bytes.BaseMid =
LOWBYTE(HIGHWORD(SelectorBase));
00608 GdtEntry->HighWord.Bytes.BaseHi =
HIGHBYTE(HIGHWORD(SelectorBase));
00609 GdtEntry->HighWord.Bits.Pres = 1;
00610 GdtEntry->HighWord.Bits.Type = TYPE_DATA;
00611 GdtEntry->HighWord.Bits.Dpl = DPL_SYSTEM;
00612
for (i = 1; i < (ULONG)
KeNumberProcessors; i++) {
00613 GdtEntry1 = (PKGDTENTRY)(
KiAbiosGdt[i] + Selector);
00614 *GdtEntry1 = *GdtEntry;
00615 }
00616 ExReleaseSpinLock(&
KiAbiosGdtLock, OldIrql);
00617
return STATUS_SUCCESS;
00618 }
00619 }
00620
00621
VOID
00622 Ki386InitializeGdtFreeList (
00623
PKFREE_GDT_ENTRY EndOfGdt
00624 )
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642 {
00643
PKFREE_GDT_ENTRY GdtEntry;
00644
00645 GdtEntry = EndOfGdt - 1;
00646
KiFreeGdtListHead = (
PKFREE_GDT_ENTRY)0;
00647
while (GdtEntry != (
PKFREE_GDT_ENTRY)
KiAbiosGetGdt() +
00648
RESERVED_GDT_ENTRIES - 1) {
00649
if (GdtEntry->
Present == 0) {
00650 GdtEntry->
Flink =
KiFreeGdtListHead;
00651
KiFreeGdtListHead = GdtEntry;
00652
KiNumberFreeSelectors++;
00653 }
00654 GdtEntry--;
00655 }
00656 }
00657
00658
VOID
00659 KiInitializeAbios (
00660 IN UCHAR Processor
00661 )
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680 {
00681
00682 ULONG GdtLength;
00683 PKGDTENTRY AliasGdtSelectorEntry;
00684
PKFREE_GDT_ENTRY EndOfGdt;
00685
00686
00687
00688
00689
00690
KiCommonDataArea =
KeLoaderBlock->
u.I386.CommonDataArea;
00691
00692
00693
00694
00695
00696
if (
KiCommonDataArea ==
NULL || Processor != 0) {
00697
KiAbiosPresent =
FALSE;
00698 }
else {
00699
KiAbiosPresent =
TRUE;
00700 }
00701
00702
00703
00704
00705
00706
KeInitializeSpinLock( &
KiAbiosGdtLock );
00707
KeInitializeSpinLock( &
KiAbiosLidTableLock );
00708
00709
00710
00711
00712
00713
KiAbiosGdt[Processor] =
KiAbiosGetGdt();
00714
00715 AliasGdtSelectorEntry = (PKGDTENTRY)(
KiAbiosGetGdt() +
KGDT_GDT_ALIAS);
00716 GdtLength = 1 + (ULONG)(AliasGdtSelectorEntry->LimitLow) +
00717 (ULONG)(AliasGdtSelectorEntry->HighWord.Bits.LimitHi << 16);
00718 EndOfGdt = (
PKFREE_GDT_ENTRY)(
KiAbiosGetGdt() + GdtLength);
00719
00720
00721
00722
00723
00724
KiStack16GdtEntry =
KiAbiosGetGdt() +
KGDT_STACK16;
00725
00726
KiInitializeAbiosGdtEntry(
00727 (PKGDTENTRY)
KiStack16GdtEntry,
00728 0
L,
00729 0xffff,
00730 TYPE_DATA
00731 );
00732
00733
00734
00735
00736
00737
KiInitializeAbiosGdtEntry(
00738 (PKGDTENTRY)(
KiAbiosGetGdt() +
KGDT_CDA16),
00739 (ULONG)
KiCommonDataArea,
00740 0xffff,
00741 TYPE_DATA
00742 );
00743
00744
00745
00746
00747
00748
KiInitializeAbiosGdtEntry(
00749 (PKGDTENTRY)(
KiAbiosGetGdt() +
KGDT_CODE16),
00750 (ULONG)&
KiI386CallAbios,
00751 (ULONG)&
KiEndOfCode16 - (ULONG)&
KiI386CallAbios - 1,
00752 0x18
00753 );
00754
00755
00756
00757
00758
00759
if (Processor == 0) {
00760
Ki386InitializeGdtFreeList(EndOfGdt);
00761 }
00762 }