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.

1297 lines
35 KiB

  1. /*++
  2. Copyright (c) 1995 Intel Corporation
  3. Module Name:
  4. i64fw.c
  5. Abstract:
  6. This module implements the routines that transfer control
  7. from the kernel to the PAL and SAL code.
  8. Author:
  9. Arad Rostampour (arad@fc.hp.com) Mar-21-99
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include "halp.h"
  15. #include "arc.h"
  16. #include "arccodes.h"
  17. #include "i64fw.h"
  18. #include <efi.h>
  19. extern KSPIN_LOCK HalpSalSpinLock;
  20. extern KSPIN_LOCK HalpSalStateInfoSpinLock;
  21. BOOLEAN
  22. MmSetPageProtection(
  23. IN PVOID VirtualAddress,
  24. IN SIZE_T NumberOfBytes,
  25. IN ULONG NewProtect
  26. );
  27. VOID
  28. HalpReboot (
  29. VOID
  30. );
  31. HALP_SAL_PAL_DATA HalpSalPalData;
  32. ULONGLONG HalpSalProcPointer=0;
  33. ULONGLONG HalpSalProcGlobalPointer=0;
  34. ULONGLONG HalpPhysSalProcPointer=0;
  35. ULONGLONG HalpPhysSalProcGlobalPointer=0;
  36. ULONGLONG HalpPhysPalProcPointer=0;
  37. ULONGLONG HalpVirtPalProcPointer=0;
  38. // Testing #defines
  39. //
  40. //#define SAL_TEST
  41. //#define PAL_TEST
  42. #if DBG
  43. ULONG HalpDebugTestSalPalCall=0;
  44. #endif
  45. LONGLONG
  46. HalCallPal(
  47. IN ULONGLONG FunctionIndex,
  48. IN ULONGLONG Arguement1,
  49. IN ULONGLONG Arguement2,
  50. IN ULONGLONG Arguement3,
  51. OUT PULONGLONG ReturnValue0,
  52. OUT PULONGLONG ReturnValue1,
  53. OUT PULONGLONG ReturnValue2,
  54. OUT PULONGLONG ReturnValue3
  55. )
  56. /*++
  57. --*/
  58. {
  59. //
  60. // Will interface to PAL Calls.
  61. //
  62. LONGLONG Status;
  63. SAL_PAL_RETURN_VALUES rv = {0};
  64. PSAL_PAL_RETURN_VALUES p = &rv;
  65. Status = (LONGLONG) HalpPalCall(FunctionIndex,Arguement1,Arguement2,Arguement3,p);
  66. if (ReturnValue0 != 0) // Check the pointer is not NULL
  67. *ReturnValue0 = (ULONGLONG)(p -> ReturnValues[0]);
  68. if (ReturnValue1 != 0) // check the pointer is not NULL
  69. *ReturnValue1 = (ULONGLONG)(p -> ReturnValues[1]);
  70. if (ReturnValue2 != 0) // check the pointer is not NULL
  71. *ReturnValue2 = (ULONGLONG)(p -> ReturnValues[2]);
  72. if (ReturnValue3 != 0) // check the pointer is not NULL
  73. *ReturnValue3 = (ULONGLONG)(p -> ReturnValues[3]);
  74. return Status;
  75. }
  76. SAL_PAL_RETURN_VALUES
  77. HalpSalProcPhysical(
  78. IN LONGLONG FunctionId,
  79. IN LONGLONG Arg1,
  80. IN LONGLONG Arg2,
  81. IN LONGLONG Arg3,
  82. IN LONGLONG Arg4,
  83. IN LONGLONG Arg5,
  84. IN LONGLONG Arg6,
  85. IN LONGLONG Arg7
  86. )
  87. /*++
  88. Routine Description:
  89. This function is a wrapper for making a physical mode SAL call. This
  90. function's only job is to provide the stack and backing store pointers
  91. needed by HalpSalProcPhysicalEx.
  92. Arguments:
  93. FunctionId - The SAL function ID.
  94. Arg1 through Arg7 - The values to be passed to SAL_PROC.
  95. Return Value:
  96. A SAL_PAL_RETURN_VALUES structure filled in with the data returned by
  97. HalpSalProcPhysicalEx.
  98. --*/
  99. {
  100. ULONGLONG StackPointer;
  101. ULONGLONG BackingStorePointer;
  102. ULONGLONG StackBase;
  103. //
  104. // Load the addresses of the stack and backing store reserved for
  105. // physical mode SAL calls on this processor.
  106. //
  107. StackBase = PCR->HalReserved[PROCESSOR_PHYSICAL_FW_STACK_INDEX];
  108. StackPointer = GET_FW_STACK_POINTER(StackBase);
  109. BackingStorePointer = GET_FW_BACKING_STORE_POINTER(StackBase);
  110. //
  111. // Branch to the assembly routine that makes the actual SAL call.
  112. //
  113. return HalpSalProcPhysicalEx(
  114. FunctionId,
  115. Arg1,
  116. Arg2,
  117. Arg3,
  118. Arg4,
  119. Arg5,
  120. Arg6,
  121. Arg7,
  122. (LONGLONG) StackPointer,
  123. (LONGLONG) BackingStorePointer
  124. );
  125. }
  126. SAL_STATUS
  127. HalpSalCall(
  128. IN LONGLONG FunctionId,
  129. IN LONGLONG Arg1,
  130. IN LONGLONG Arg2,
  131. IN LONGLONG Arg3,
  132. IN LONGLONG Arg4,
  133. IN LONGLONG Arg5,
  134. IN LONGLONG Arg6,
  135. IN LONGLONG Arg7,
  136. OUT PSAL_PAL_RETURN_VALUES ReturnValues
  137. )
  138. /*++
  139. Routine Description:
  140. This function is a wrapper function for making a SAL call. Callers within the
  141. HAL must use this function to call the SAL.
  142. Arguments:
  143. FunctionId - The SAL function ID
  144. Arg1-Arg7 - SAL defined arguments for each call
  145. ReturnValues - A pointer to an array of 4 64-bit return values
  146. Return Value:
  147. SAL's return status, return value 0, is returned in addition to the ReturnValues structure
  148. being filled
  149. --*/
  150. {
  151. KIRQL OldIrql;
  152. KIRQL TempIrql;
  153. BOOLEAN fixLogId;
  154. HALP_SAL_PROC SalProc;
  155. //
  156. // Zero out the return buffer.
  157. //
  158. RtlZeroMemory(ReturnValues,sizeof(SAL_PAL_RETURN_VALUES));
  159. //
  160. // Choose a SAL call dispatcher depending upon whether a virtual mapping
  161. // for the SAL exists. If a virtual mapping isn't in place we'll try
  162. // to make the call in physical mode. Return SAL_STATUS_NOT_IMPLEMENTED
  163. // if we aren't configured to make calls in either mode.
  164. //
  165. if (!NT_SUCCESS(HalpSalPalData.Status) || HalpSalProcPointer == 0) {
  166. //
  167. // We've already ruled out a virtual mode call. If possible
  168. // we'll try to make an equivalent physical mode call in this
  169. // case.
  170. //
  171. if (HalpPhysSalProcPointer != 0) {
  172. SalProc = HalpSalProcPhysical;
  173. } else {
  174. return SAL_STATUS_NOT_IMPLEMENTED;
  175. }
  176. } else {
  177. SalProc = HalpSalProc;
  178. }
  179. fixLogId = (HalpSalPalData.Flags & HALP_SALPAL_FIX_MCE_LOG_ID) != 0;
  180. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  181. switch (FunctionId) {
  182. // These calls are neither re-entrant, nor MP-safe as defined by the SAL spec
  183. case SAL_SET_VECTORS:
  184. case SAL_MC_SET_PARAMS:
  185. case SAL_FREQ_BASE:
  186. KiAcquireSpinLock(&HalpSalSpinLock);
  187. *ReturnValues = SalProc(FunctionId,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7);
  188. KiReleaseSpinLock(&HalpSalSpinLock);
  189. break;
  190. case SAL_GET_STATE_INFO:
  191. KiAcquireSpinLock(&HalpSalStateInfoSpinLock);
  192. *ReturnValues = SalProc(FunctionId,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7);
  193. if ( fixLogId && (ReturnValues->ReturnValues[0] >= (LONGLONG)0) ) {
  194. // ERROR_RECORD_HEADER.Id++
  195. *(PULONGLONG)((ULONGLONG)Arg3) = ++HalpSalPalData.Reserved[0];
  196. }
  197. KiReleaseSpinLock(&HalpSalStateInfoSpinLock);
  198. break;
  199. case SAL_GET_STATE_INFO_SIZE:
  200. case SAL_CLEAR_STATE_INFO:
  201. KiAcquireSpinLock(&HalpSalStateInfoSpinLock);
  202. *ReturnValues = SalProc(FunctionId,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7);
  203. KiReleaseSpinLock(&HalpSalStateInfoSpinLock);
  204. break;
  205. case SAL_PCI_CONFIG_READ:
  206. case SAL_PCI_CONFIG_WRITE:
  207. KiAcquireSpinLock(&HalpSalSpinLock);
  208. *ReturnValues = SalProc(FunctionId,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7);
  209. KiReleaseSpinLock(&HalpSalSpinLock);
  210. break;
  211. //
  212. // Move these to MP safe after SAL is fixed
  213. // Kernel ensures only one CACHE_FLUSH at a time
  214. //
  215. case SAL_CACHE_INIT:
  216. case SAL_CACHE_FLUSH:
  217. if ( HalpSalPalData.Flags & HALP_SALPAL_FIX_MP_SAFE ) {
  218. KiAcquireSpinLock(&HalpSalSpinLock);
  219. *ReturnValues = SalProc(FunctionId,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7);
  220. KiReleaseSpinLock(&HalpSalSpinLock);
  221. }
  222. else
  223. *ReturnValues = SalProc(FunctionId,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7);
  224. break;
  225. //
  226. // These SAL calls are MP-safe, but not re-entrant
  227. //
  228. case SAL_MC_RENDEZ:
  229. *ReturnValues = SalProc(FunctionId,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7);
  230. break;
  231. //
  232. // These calls are not supported at this time
  233. //
  234. case SAL_UPDATE_PAL: // needs end of firmware space to be mapped, and possible authentication code to execute
  235. default:
  236. ReturnValues->ReturnValues[0] = SAL_STATUS_NOT_IMPLEMENTED;
  237. }
  238. KeLowerIrql(OldIrql);
  239. #ifdef SAL_TEST
  240. if (ReturnValues->ReturnValues[0] == SAL_STATUS_NOT_IMPLEMENTED) {
  241. InternalTestSal(FunctionId,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7,ReturnValues);
  242. }
  243. #endif
  244. #if 0
  245. // To avoid Kd hangs while flushing and then MP synchronization issues..
  246. HalDebugPrint(( HAL_INFO,
  247. "HAL: Got out of SAL call #0x%I64x with status 0x%I64x and RetVals 0x%I64x, 0x%I64x, 0x%I64x\n",
  248. FunctionId,
  249. ReturnValues->ReturnValues[0],
  250. ReturnValues->ReturnValues[1],
  251. ReturnValues->ReturnValues[2],
  252. ReturnValues->ReturnValues[3] ));
  253. #endif
  254. return (ReturnValues->ReturnValues[0]);
  255. }
  256. PAL_STATUS
  257. HalpPalCall(
  258. IN LONGLONG FunctionId,
  259. IN LONGLONG Arg1,
  260. IN LONGLONG Arg2,
  261. IN LONGLONG Arg3,
  262. OUT PSAL_PAL_RETURN_VALUES ReturnValues
  263. )
  264. /*++
  265. Routine Description:
  266. This function is a wrapper function for making a PAL call. Callers within the
  267. HAL must use this function to call the PAL.
  268. Arguments:
  269. FunctionId - The PAL function ID
  270. Arg1-Arg3 - PAL defined arguments for each call
  271. ReturnValues - A pointer to an array of 4 64-bit return values
  272. Return Value:
  273. PAL's return status, return value 0, is returned in addition to the ReturnValues structure
  274. being filled
  275. Assumptions:
  276. PAL is being called with psr.bn = 1 in all cases (not from an interrupted state)
  277. --*/
  278. {
  279. // Zero out the return buffer
  280. RtlZeroMemory(ReturnValues,sizeof(SAL_PAL_RETURN_VALUES));
  281. // Only allow PAL calls that are supported
  282. switch (FunctionId) {
  283. // Virtual mode PAL calls
  284. case PAL_CACHE_FLUSH:
  285. case PAL_CACHE_INFO:
  286. case PAL_CACHE_PROT_INFO:
  287. case PAL_CACHE_SUMMARY:
  288. case PAL_PTCE_INFO:
  289. case PAL_VM_INFO:
  290. case PAL_VM_PAGE_SIZE:
  291. case PAL_VM_SUMMARY:
  292. case PAL_PERF_MON_INFO:
  293. case PAL_MC_CLEAR_LOG:
  294. case PAL_MC_DRAIN:
  295. case PAL_MC_ERROR_INFO:
  296. case PAL_HALT_LIGHT:
  297. case PAL_PREFETCH_VISIBILITY:
  298. case PAL_SHUTDOWN:
  299. case PAL_FREQ_RATIOS:
  300. case PAL_VERSION:
  301. case PAL_MEM_ATTRIB:
  302. case PAL_DEBUG_INFO:
  303. case PAL_FIXED_ADDR:
  304. case PAL_FREQ_BASE:
  305. case PAL_PLATFORM_ADDR:
  306. case PAL_REGISTER_INFO:
  307. case PAL_RSE_INFO:
  308. // PAL is MP-safe, but not re-entrant, HalpPalProc/HalpPalProcPhysicalStatic disables interrupts.
  309. //
  310. // FIXFIX: Temporary solution to make sure we have a valid Pal TR per processor
  311. // to make virtual PAL calls.
  312. // PCR->HalReserved[ PROCESSOR_PHYSICAL_FW_STACK_INDEX] gets set for every processor
  313. // by call to HalpAllocateProcessorPhysicalCallStacks during SalPal init
  314. //
  315. if (HalpVirtPalProcPointer && PCR->HalReserved[PROCESSOR_PHYSICAL_FW_STACK_INDEX]) {
  316. *ReturnValues = HalpPalProc(FunctionId,Arg1,Arg2,Arg3);
  317. } else if (HalpPhysPalProcPointer) {
  318. // call in physical mode
  319. *ReturnValues = HalpPalProcPhysicalStatic(FunctionId, Arg1, Arg2, Arg3);
  320. } else {
  321. // Hal PalProc pointers are not setup yet
  322. ReturnValues->ReturnValues[0] = PAL_STATUS_NOT_IMPLEMENTED;
  323. }
  324. break;
  325. // Physical mode, static PAL calls
  326. case PAL_HALT:
  327. case PAL_CACHE_INIT:
  328. case PAL_BUS_GET_FEATURES:
  329. case PAL_BUS_SET_FEATURES:
  330. case PAL_PROC_GET_FEATURES:
  331. case PAL_PROC_SET_FEATURES:
  332. case PAL_MC_DYNAMIC_STATE:
  333. case PAL_MC_EXPECTED:
  334. case PAL_MC_REGISTER_MEM:
  335. case PAL_MC_RESUME:
  336. case PAL_CACHE_LINE_INIT:
  337. case PAL_MEM_FOR_TEST:
  338. case PAL_COPY_INFO:
  339. case PAL_ENTER_IA_32_ENV:
  340. case PAL_PMI_ENTRYPOINT:
  341. //
  342. // PAL is MP-safe, but not re-entrant, HalpPalProcPhysicalStatic
  343. // disables interrupts.
  344. //
  345. if (HalpPhysPalProcPointer) {
  346. *ReturnValues = HalpPalProcPhysicalStatic(FunctionId, Arg1, Arg2, Arg3);
  347. } else {
  348. // Hal PalProc pointers are not setup yet
  349. ReturnValues->ReturnValues[0] = PAL_STATUS_NOT_IMPLEMENTED;
  350. }
  351. break;
  352. // Physical mode, stacked PAL calls
  353. case PAL_VM_TR_READ:
  354. case PAL_CACHE_READ:
  355. case PAL_CACHE_WRITE:
  356. case PAL_TEST_PROC:
  357. case PAL_COPY_PAL:
  358. case PAL_HALT_INFO:
  359. {
  360. ULONGLONG StackBase;
  361. ULONGLONG BackingStorePointer;
  362. ULONGLONG StackPointer;
  363. //
  364. // Load the addresses of the stack and backing store reserved for
  365. // physical mode PAL calls on this processor.
  366. //
  367. StackBase = PCR->HalReserved[PROCESSOR_PHYSICAL_FW_STACK_INDEX];
  368. StackPointer = GET_FW_STACK_POINTER(StackBase);
  369. BackingStorePointer = GET_FW_BACKING_STORE_POINTER(StackBase);
  370. //
  371. // PAL is MP-safe, but not re-entrant, HalpPalProcPhysicalStacked
  372. // disables interrupts.
  373. //
  374. if (HalpPhysPalProcPointer) {
  375. *ReturnValues = HalpPalProcPhysicalStacked(
  376. FunctionId,
  377. Arg1,
  378. Arg2,
  379. Arg3,
  380. (LONGLONG) StackPointer,
  381. (LONGLONG) BackingStorePointer
  382. );
  383. } else {
  384. // Hal PalProc pointers are not setup yet
  385. ReturnValues->ReturnValues[0] = PAL_STATUS_NOT_IMPLEMENTED;
  386. }
  387. }
  388. break;
  389. default:
  390. HalDebugPrint(( HAL_ERROR, "HAL: Unknown PAL Call ProcId #0x%I64x\n", FunctionId ));
  391. ReturnValues->ReturnValues[0] = PAL_STATUS_NOT_IMPLEMENTED;
  392. }
  393. #ifdef PAL_TEST
  394. if (ReturnValues->ReturnValues[0] == PAL_STATUS_NOT_IMPLEMENTED) {
  395. InternalTestPal(FunctionId,Arg1,Arg2,Arg3,ReturnValues);
  396. }
  397. #endif
  398. #if 0
  399. // To avoid Kd hangs while flushing...
  400. HalDebugPrint(( HAL_INFO,
  401. "HAL: Got out of PAL call #0x%I64x with status 0x%I64x and RetVals 0x%I64x, 0x%I64x, 0x%I64x\n",
  402. FunctionId,
  403. ReturnValues->ReturnValues[0],
  404. ReturnValues->ReturnValues[1],
  405. ReturnValues->ReturnValues[2],
  406. ReturnValues->ReturnValues[3] ));
  407. #endif
  408. return (ReturnValues->ReturnValues[0]);
  409. }
  410. VOID
  411. HalReturnToFirmware(
  412. IN FIRMWARE_ENTRY Routine
  413. )
  414. /*++
  415. Routine Description:
  416. Returns control to the firmware routine specified. Since the simulation
  417. does not provide PAL and SAL support, it just stops the system.
  418. System reboot can be done here.
  419. Arguments:
  420. Routine - Supplies a value indicating which firmware routine to invoke.
  421. Return Value:
  422. Does not return.
  423. --*/
  424. {
  425. switch (Routine) {
  426. case HalHaltRoutine:
  427. case HalPowerDownRoutine:
  428. case HalRestartRoutine:
  429. case HalRebootRoutine:
  430. HalpReboot();
  431. break;
  432. default:
  433. HalDebugPrint(( HAL_INFO, "HAL: HalReturnToFirmware called\n" ));
  434. DbgBreakPoint();
  435. break;
  436. }
  437. }
  438. ARC_STATUS
  439. HalGetEnvironmentVariable (
  440. IN PCHAR Variable,
  441. IN USHORT Length,
  442. OUT PCHAR Buffer
  443. )
  444. /*++
  445. Routine Description:
  446. This function locates an environment variable and returns its value.
  447. The following system environment variables are supported:
  448. variable value
  449. LastKnownGood FALSE
  450. SYSTEMPARTITION multi(0)disk(0)rdisk(0)partition(1)
  451. OSLOADER multi(0)disk(0)rdisk(0)partition(1)\osloader.exe
  452. OSLOADPARTITION multi(0)disk(0)rdisk(0)partition(1)
  453. OSLOADFILENAME \WINNT
  454. LOADIDENTIFIER Windows NT
  455. COUNTDOWN 10
  456. AUTOLOAD YES
  457. The only environment variable this implementation supports is
  458. "LastKnownGood". The returned value is always "FALSE".
  459. Arguments:
  460. Variable - Supplies a pointer to a zero terminated environment variable
  461. name.
  462. Length - Supplies the length of the value buffer in bytes.
  463. Buffer - Supplies a pointer to a buffer that receives the variable value.
  464. Return Value:
  465. ESUCCESS is returned if the enviroment variable is located. Otherwise,
  466. ENOENT is returned.
  467. --*/
  468. {
  469. return ENOENT;
  470. }
  471. ARC_STATUS
  472. HalSetEnvironmentVariable (
  473. IN PCHAR Variable,
  474. IN PCHAR Value
  475. )
  476. /*++
  477. Routine Description:
  478. This function creates an environment variable with the specified value.
  479. The environment variable this implementation supports is
  480. LastKnownGood
  481. SYSTEMPARTITION
  482. OSLOADER
  483. OSLOADPARTITION
  484. OSLOADFILENAME
  485. OSLOADOPTIONS
  486. LOADIDENTIFIER
  487. COUNTDOWN
  488. AUTOLOAD
  489. For all bug LastKnowGood we return ESUCCESS, but don't actually do
  490. anything.
  491. Arguments:
  492. Variable - Supplies a pointer to an environment variable name.
  493. Value - Supplies a pointer to the environment variable value.
  494. Return Value:
  495. ESUCCESS is returned if the environment variable is created. Otherwise,
  496. ENOMEM is returned.
  497. --*/
  498. {
  499. return ENOENT;
  500. }
  501. NTSTATUS
  502. HalGetEnvironmentVariableEx (
  503. IN PWSTR VariableName,
  504. IN LPGUID VendorGuid,
  505. OUT PVOID Value,
  506. IN OUT PULONG ValueLength,
  507. OUT PULONG Attributes OPTIONAL
  508. )
  509. /*++
  510. Routine Description:
  511. This function locates an environment variable and returns its value.
  512. Arguments:
  513. VariableName - The name of the variable to query. This is a null-terminated
  514. Unicode string.
  515. VendorGuid - The GUID for the vendor associated with the variable.
  516. Value - The address of the buffer into which the variable value is to be copied.
  517. ValueLength - On input, the length in bytes of the Value buffer. On output,
  518. the length in bytes of the variable value. If the input buffer is large
  519. enough, then ValueLength indicates the amount of data copied into Value.
  520. If the input buffer is too small, then nothing is copied into the buffer,
  521. and ValueLength indicates the required buffer length.
  522. Attributes - Returns the attributes of the variable.
  523. Return Value:
  524. STATUS_SUCCESS The function succeeded.
  525. STATUS_BUFFER_TOO_SMALL The input buffer was too small.
  526. STATUS_VARIABLE_NOT_FOUND The requested variable does not exist.
  527. STATUS_INVALID_PARAMETER One of the parameters is invalid.
  528. STATUS_UNSUPPORTED The HAL does not support this function.
  529. STATUS_UNSUCCESSFUL The firmware returned an unrecognized error.
  530. --*/
  531. {
  532. NTSTATUS ntStatus;
  533. EFI_STATUS efiStatus;
  534. ULONGLONG wideValueLength = *ValueLength;
  535. ULONGLONG wideAttributes;
  536. efiStatus = HalpCallEfi (
  537. EFI_GET_VARIABLE_INDEX,
  538. (ULONGLONG)VariableName,
  539. (ULONGLONG)VendorGuid,
  540. (ULONGLONG)&wideAttributes,
  541. (ULONGLONG)&wideValueLength,
  542. (ULONGLONG)Value,
  543. 0,
  544. 0,
  545. 0
  546. );
  547. *ValueLength = (ULONG)wideValueLength;
  548. if ( ARGUMENT_PRESENT(Attributes) ) {
  549. *Attributes = (ULONG)wideAttributes;
  550. }
  551. switch (efiStatus) {
  552. case EFI_SUCCESS:
  553. ntStatus = STATUS_SUCCESS;
  554. break;
  555. case EFI_NOT_FOUND:
  556. ntStatus = STATUS_VARIABLE_NOT_FOUND;
  557. break;
  558. case EFI_BUFFER_TOO_SMALL:
  559. ntStatus = STATUS_BUFFER_TOO_SMALL;
  560. break;
  561. case EFI_INVALID_PARAMETER:
  562. ntStatus = STATUS_INVALID_PARAMETER;
  563. break;
  564. default:
  565. ntStatus = STATUS_UNSUCCESSFUL;
  566. break;
  567. }
  568. return ntStatus;
  569. }
  570. NTSTATUS
  571. HalSetEnvironmentVariableEx (
  572. IN PWSTR VariableName,
  573. IN LPGUID VendorGuid,
  574. IN PVOID Value,
  575. IN ULONG ValueLength,
  576. IN ULONG Attributes
  577. )
  578. /*++
  579. Routine Description:
  580. This function creates an environment variable with the specified value.
  581. Arguments:
  582. VariableName - The name of the variable to set. This is a null-terminated
  583. Unicode string.
  584. VendorGuid - The GUID for the vendor associated with the variable.
  585. Value - The address of the buffer containing the new variable value.
  586. ValueLength - The length in bytes of the Value buffer.
  587. Attributes - The attributes of the variable. The attribute bit
  588. VARIABLE_ATTRIBUTE_NON_VOLATILE MUST be set.
  589. Return Value:
  590. STATUS_SUCCESS The function succeeded.
  591. STATUS_INSUFFICIENT_RESOURCES Not enough storage is available.
  592. STATUS_INVALID_PARAMETER One of the parameters is invalid.
  593. STATUS_UNSUPPORTED The HAL does not support this function.
  594. STATUS_UNSUCCESSFUL The firmware returned an unrecognized error.
  595. --*/
  596. {
  597. NTSTATUS ntStatus;
  598. EFI_STATUS efiStatus;
  599. if ( (Attributes & VARIABLE_ATTRIBUTE_NON_VOLATILE) == 0 ) {
  600. return STATUS_INVALID_PARAMETER;
  601. }
  602. //
  603. // First, delete the old value, if it exists. This is necessary to ensure that
  604. // the attributes specified to this routine are correctly applied.
  605. //
  606. efiStatus = HalpCallEfi (
  607. EFI_SET_VARIABLE_INDEX,
  608. (ULONGLONG)VariableName,
  609. (ULONGLONG)VendorGuid,
  610. (ULONGLONG)0, // Attributes
  611. (ULONGLONG)0, // ValueLength
  612. (ULONGLONG)NULL, // Value
  613. 0,
  614. 0,
  615. 0
  616. );
  617. //
  618. // Now create the new variable, unless the ValueLength is zero. In that
  619. // case, the caller actually wanted the variable deleted, which we just did.
  620. //
  621. if (ValueLength != 0) {
  622. efiStatus = HalpCallEfi (
  623. EFI_SET_VARIABLE_INDEX,
  624. (ULONGLONG)VariableName,
  625. (ULONGLONG)VendorGuid,
  626. (ULONGLONG)EFI_VARIABLE_ATTRIBUTE,
  627. (ULONGLONG)ValueLength,
  628. (ULONGLONG)Value,
  629. 0,
  630. 0,
  631. 0
  632. );
  633. }
  634. switch (efiStatus) {
  635. case EFI_SUCCESS:
  636. ntStatus = STATUS_SUCCESS;
  637. break;
  638. case EFI_NOT_FOUND:
  639. ntStatus = STATUS_VARIABLE_NOT_FOUND;
  640. break;
  641. case EFI_OUT_OF_RESOURCES:
  642. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  643. break;
  644. case EFI_INVALID_PARAMETER:
  645. ntStatus = STATUS_INVALID_PARAMETER;
  646. break;
  647. default:
  648. ntStatus = STATUS_UNSUCCESSFUL;
  649. break;
  650. }
  651. return ntStatus;
  652. }
  653. NTSTATUS
  654. HalEnumerateEnvironmentVariablesEx (
  655. IN ULONG InformationClass,
  656. OUT PVOID Buffer,
  657. IN OUT PULONG BufferLength
  658. )
  659. /*++
  660. Routine Description:
  661. This function returns information about system environment variables.
  662. Arguments:
  663. InformationClass - Specifies the type of information to return.
  664. Buffer - The address of the buffer that is to receive the returned data.
  665. The format of the returned data depends on InformationClass.
  666. BufferLength - On input, the length in bytes of the buffer. On output,
  667. the length in bytes of the returned data. If the input buffer is
  668. large enough, then BufferLength indicates the amount of data copied
  669. into Buffer. If the input buffer is too small, then BufferLength
  670. indicates the required buffer length.
  671. Return Value:
  672. STATUS_SUCCESS The function succeeded.
  673. STATUS_BUFFER_TOO_SMALL The input buffer was too small.
  674. STATUS_INVALID_PARAMETER One of the parameters is invalid.
  675. STATUS_UNSUPPORTED The HAL does not support this function.
  676. STATUS_UNSUCCESSFUL The firmware returned an unrecognized error.
  677. --*/
  678. {
  679. NTSTATUS ntStatus = STATUS_SUCCESS;
  680. EFI_STATUS efiStatus;
  681. PUCHAR currentPtr;
  682. PVARIABLE_NAME name;
  683. PVARIABLE_NAME_AND_VALUE nameAndValue;
  684. PVARIABLE_NAME previousEntry;
  685. PWCHAR previousName;
  686. ULONG variableNameLength;
  687. GUID guid;
  688. ULONG baseLength;
  689. ULONG remainingLength;
  690. PUCHAR valuePtr;
  691. ULONG valueLength;
  692. PULONG attrPtr;
  693. LOGICAL filling;
  694. ULONG requiredLength;
  695. #define MAX_VARIABLE_NAME 255
  696. WCHAR variableName[MAX_VARIABLE_NAME + 1];
  697. if ( (InformationClass != VARIABLE_INFORMATION_NAMES) &&
  698. (InformationClass != VARIABLE_INFORMATION_VALUES) ) {
  699. return STATUS_INVALID_PARAMETER;
  700. }
  701. if ( ALIGN_DOWN_POINTER(Buffer, ULONG) != Buffer ) {
  702. return STATUS_INVALID_PARAMETER;
  703. }
  704. if ( InformationClass == VARIABLE_INFORMATION_NAMES ) {
  705. baseLength = FIELD_OFFSET( VARIABLE_NAME, Name );
  706. } else {
  707. baseLength = FIELD_OFFSET( VARIABLE_NAME_AND_VALUE, Name );
  708. }
  709. currentPtr = Buffer;
  710. remainingLength = *BufferLength;
  711. filling = (LOGICAL)(remainingLength != 0);
  712. if ( !filling ) {
  713. ntStatus = STATUS_BUFFER_TOO_SMALL;
  714. }
  715. previousEntry = NULL;
  716. variableName[0] = 0;
  717. while ( TRUE ) {
  718. variableNameLength = (MAX_VARIABLE_NAME + 1) * sizeof(WCHAR);
  719. {
  720. ULONGLONG wideLength = variableNameLength;
  721. efiStatus = HalpCallEfi (
  722. EFI_GET_NEXT_VARIABLE_NAME_INDEX,
  723. (ULONGLONG)&wideLength,
  724. (ULONGLONG)variableName,
  725. (ULONGLONG)&guid,
  726. 0,
  727. 0,
  728. 0,
  729. 0,
  730. 0
  731. );
  732. variableNameLength = (ULONG)wideLength;
  733. }
  734. switch (efiStatus) {
  735. case EFI_SUCCESS:
  736. break;
  737. case EFI_NOT_FOUND:
  738. break;
  739. default:
  740. ntStatus = STATUS_UNSUCCESSFUL;
  741. break;
  742. }
  743. if ( efiStatus != EFI_SUCCESS ) {
  744. break;
  745. }
  746. if ( ALIGN_UP_POINTER(currentPtr, ULONG) != currentPtr ) {
  747. PUCHAR alignedPtr = ALIGN_UP_POINTER( currentPtr, ULONG );
  748. ULONG fill = (ULONG)(alignedPtr - currentPtr);
  749. currentPtr = alignedPtr;
  750. if ( remainingLength < fill ) {
  751. filling = FALSE;
  752. remainingLength = 0;
  753. ntStatus = STATUS_BUFFER_TOO_SMALL;
  754. } else {
  755. remainingLength -= fill;
  756. }
  757. }
  758. requiredLength = baseLength + variableNameLength;
  759. if ( InformationClass != VARIABLE_INFORMATION_NAMES ) {
  760. requiredLength = ALIGN_UP( requiredLength, ULONG );
  761. }
  762. if ( remainingLength < requiredLength ) {
  763. remainingLength = 0;
  764. filling = FALSE;
  765. ntStatus = STATUS_BUFFER_TOO_SMALL;
  766. } else {
  767. remainingLength -= requiredLength;
  768. }
  769. name = (PVARIABLE_NAME)currentPtr;
  770. nameAndValue = (PVARIABLE_NAME_AND_VALUE)currentPtr;
  771. if ( InformationClass == VARIABLE_INFORMATION_NAMES ) {
  772. if ( filling ) {
  773. RtlCopyMemory( &name->VendorGuid, &guid, sizeof(GUID) );
  774. wcscpy( name->Name, variableName );
  775. if ( previousEntry != NULL ) {
  776. previousEntry->NextEntryOffset = (ULONG)(currentPtr - (PUCHAR)previousEntry);
  777. }
  778. previousEntry = (PVARIABLE_NAME)currentPtr;
  779. }
  780. currentPtr += requiredLength;
  781. } else {
  782. ULONGLONG wideLength;
  783. ULONGLONG wideAttr;
  784. if ( filling ) {
  785. RtlCopyMemory( &nameAndValue->VendorGuid, &guid, sizeof(GUID) );
  786. wcscpy( nameAndValue->Name, variableName );
  787. valuePtr = (PUCHAR)nameAndValue->Name + variableNameLength;
  788. valuePtr = ALIGN_UP_POINTER( valuePtr, ULONG );
  789. valueLength = remainingLength;
  790. attrPtr = &nameAndValue->Attributes;
  791. nameAndValue->ValueOffset = (ULONG)(valuePtr - (PUCHAR)nameAndValue);
  792. } else {
  793. valuePtr = NULL;
  794. valueLength = 0;
  795. attrPtr = NULL;
  796. }
  797. wideLength = valueLength;
  798. efiStatus = HalpCallEfi (
  799. EFI_GET_VARIABLE_INDEX,
  800. (ULONGLONG)variableName,
  801. (ULONGLONG)&guid,
  802. (ULONGLONG)&wideAttr,
  803. (ULONGLONG)&wideLength,
  804. (ULONGLONG)valuePtr,
  805. 0,
  806. 0,
  807. 0
  808. );
  809. valueLength = (ULONG)wideLength;
  810. if ( attrPtr != NULL ) {
  811. *attrPtr = (ULONG)wideAttr;
  812. }
  813. switch (efiStatus) {
  814. case EFI_SUCCESS:
  815. if ( filling ) {
  816. nameAndValue->ValueLength = valueLength;
  817. remainingLength -= valueLength;
  818. if ( previousEntry != NULL ) {
  819. previousEntry->NextEntryOffset = (ULONG)(currentPtr - (PUCHAR)previousEntry);
  820. }
  821. previousEntry = (PVARIABLE_NAME)currentPtr;
  822. }
  823. break;
  824. case EFI_BUFFER_TOO_SMALL:
  825. efiStatus = EFI_SUCCESS;
  826. remainingLength = 0;
  827. filling = FALSE;
  828. ntStatus = STATUS_BUFFER_TOO_SMALL;
  829. break;
  830. default:
  831. ntStatus = STATUS_UNSUCCESSFUL;
  832. break;
  833. }
  834. if ( efiStatus != EFI_SUCCESS ) {
  835. break;
  836. }
  837. currentPtr += requiredLength + valueLength;
  838. }
  839. }
  840. if ( previousEntry != NULL ) {
  841. previousEntry->NextEntryOffset = 0;
  842. }
  843. *BufferLength = (ULONG)(currentPtr - (PUCHAR)Buffer);
  844. return ntStatus;
  845. }
  846. NTSTATUS
  847. HalpGetPlatformId(
  848. OUT PHAL_PLATFORM_ID PlatformId
  849. )
  850. /*++
  851. Routine Description:
  852. This function fills in the ANSI_STRING structures for the Vendor and Device IDs out
  853. of the SalSystemTable.
  854. Arguments:
  855. PlatformId - Pointer to a structure with two ANSI_STRING structures for Vendor/DeviceIds
  856. Return Value:
  857. STATUS_SUCCESS if SalSystemTable available, otherwise STATUS_UNSUCCESSFUL
  858. Assumptions:
  859. The two strings in PlatformId will not be freed or modified, and are therefore pointing
  860. directly to the SalSystemTable.
  861. --*/
  862. {
  863. UCHAR i;
  864. // Initialize the VendorId ANSI_STRING structure to point to SalSystemTable entry
  865. // Note, both strings are either NULL terminated OR exactly 32-bytes in length and
  866. // not NULL terminated.
  867. if (!NT_SUCCESS(HalpSalPalData.Status)) {
  868. return STATUS_UNSUCCESSFUL;
  869. }
  870. i=0;;
  871. while (HalpSalPalData.SalSystemTable->OemId[i] && i < OEM_ID_LENGTH) {
  872. i++;
  873. }
  874. PlatformId->VendorId.Buffer = HalpSalPalData.SalSystemTable->OemId;
  875. PlatformId->VendorId.Length = i;
  876. PlatformId->VendorId.MaximumLength = i;
  877. // Initialize the DeviceId ANSI_STRING structure to point to SalSystemTable entry
  878. i=0;
  879. while (HalpSalPalData.SalSystemTable->ProductId[i] && i < OEM_PRODUCT_ID_LENGTH) {
  880. i++;
  881. }
  882. PlatformId->DeviceId.Buffer = HalpSalPalData.SalSystemTable->ProductId;
  883. PlatformId->DeviceId.Length = i;
  884. PlatformId->DeviceId.MaximumLength = i;
  885. return STATUS_SUCCESS;
  886. }
  887. /*****************************************************************
  888. TEST CODE FOR THE SAL AND PAL:
  889. These routines provide an infrastructure for supporting SAL and
  890. PAL calls not supported by firmware, overriding there meaning
  891. if SAL or PAL returns STATUS_NOT_IMPLEMENTED. The #define for
  892. SAL_TEST and/or PAL_TEST must be defined for this behavior.
  893. *****************************************************************/
  894. ULONG
  895. NoSalPCIRead(
  896. IN ULONG Tok,
  897. IN ULONG Size
  898. )
  899. {
  900. ULONG Data;
  901. ULONG i = Tok % sizeof(ULONG);
  902. WRITE_PORT_ULONG((PULONG)0xcf8, 0x80000000 | Tok);
  903. switch (Size) {
  904. case 1: Data = READ_PORT_UCHAR((PUCHAR)(ULongToPtr(0xcfc + i) )); break;
  905. case 2: Data = READ_PORT_USHORT((PUSHORT)(ULongToPtr(0xcfc + i) )); break;
  906. case 4: Data = READ_PORT_ULONG((PULONG)(0xcfc)); break;
  907. }
  908. return(Data);
  909. }
  910. VOID
  911. NoSalPCIWrite(
  912. IN ULONG Tok,
  913. IN ULONG Size,
  914. IN ULONG Data
  915. )
  916. {
  917. ULONG i = Tok % sizeof(ULONG);
  918. WRITE_PORT_ULONG((PULONG)0xcf8, 0x80000000 | Tok);
  919. switch (Size) {
  920. case 1: WRITE_PORT_UCHAR((PUCHAR)(ULongToPtr(0xcfc + i) ), (UCHAR)Data); break;
  921. case 2: WRITE_PORT_USHORT((PUSHORT)(ULongToPtr(0xcfc + i) ), (USHORT)Data); break;
  922. case 4: WRITE_PORT_ULONG((PULONG)(0xcfc), Data); break;
  923. }
  924. }
  925. #define PCIBUS(Tok) (((ULONG)(Tok) >> 16) & 0xff)
  926. #define PCIDEV(Tok) (((ULONG)(Tok) >> 11) & 0x1f)
  927. #define PCIFUNC(Tok) (((ULONG)(Tok) >> 8) & 0x7)
  928. #define PCIOFF(Tok) (((ULONG)(Tok) >> 2) & 0x3f)
  929. VOID
  930. InternalTestSal(
  931. IN LONGLONG FunctionId,
  932. IN LONGLONG Arg1,
  933. IN LONGLONG Arg2,
  934. IN LONGLONG Arg3,
  935. IN LONGLONG Arg4,
  936. IN LONGLONG Arg5,
  937. IN LONGLONG Arg6,
  938. IN LONGLONG Arg7,
  939. OUT PSAL_PAL_RETURN_VALUES ReturnValues
  940. )
  941. {
  942. switch (FunctionId) {
  943. case SAL_PCI_CONFIG_READ: {
  944. ULONG Data;
  945. HalDebugPrint(( HAL_INFO, "HAL: << SAL_PCI_CONFIG_READ - Bus: %d Dev: %2d Func: %d Off: %2d Size = %d ",
  946. PCIBUS(Arg1), PCIDEV(Arg1), PCIFUNC(Arg1), PCIOFF(Arg1), Arg2 ));
  947. ReturnValues->ReturnValues[0] = SAL_STATUS_SUCCESS;
  948. ReturnValues->ReturnValues[1] = Data = NoSalPCIRead((ULONG)Arg1, (ULONG)Arg2);
  949. HalDebugPrint(( HAL_INFO, " Data = 0x%08x\n", Data ));
  950. break;
  951. }
  952. case SAL_PCI_CONFIG_WRITE:
  953. HalDebugPrint(( HAL_INFO, "HAL: >> SAL_PCI_CONFIG_WRITE: Bus: %d Dev: %2d Func: %d Off: %2d Size = %d Val = 0x%08x\n",
  954. PCIBUS(Arg1), PCIDEV(Arg1), PCIFUNC(Arg1), PCIOFF(Arg1), Arg2, Arg3 ));
  955. NoSalPCIWrite((ULONG)Arg1, (ULONG)Arg2, (ULONG)Arg3);
  956. ReturnValues->ReturnValues[0] = SAL_STATUS_SUCCESS;
  957. break;
  958. default:
  959. ReturnValues->ReturnValues[0] = SAL_STATUS_NOT_IMPLEMENTED;
  960. }
  961. }
  962. VOID
  963. InternalTestPal(
  964. IN LONGLONG FunctionId,
  965. IN LONGLONG Arg1,
  966. IN LONGLONG Arg2,
  967. IN LONGLONG Arg3,
  968. OUT PSAL_PAL_RETURN_VALUES ReturnValues
  969. )
  970. {
  971. switch (FunctionId) {
  972. default:
  973. ReturnValues->ReturnValues[0] = SAL_STATUS_NOT_IMPLEMENTED;
  974. }
  975. }