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.

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