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.

2374 lines
76 KiB

  1. /*++
  2. Copyright (c) 1995 Intel Corporation
  3. Module Name:
  4. i64efi.c
  5. Abstract:
  6. This module implements the routines that transfer control
  7. from the kernel to the EFI code.
  8. Author:
  9. Bernard Lint
  10. M. Jayakumar (Muthurajan.Jayakumar@hotmail.com)
  11. Environment:
  12. Kernel mode
  13. Revision History:
  14. Neal Vu (neal.vu@intel.com), 03-Apr-2001:
  15. Added HalpGetSmBiosVersion.
  16. --*/
  17. #include "halp.h"
  18. #include "arc.h"
  19. #include "arccodes.h"
  20. #include "i64fw.h"
  21. #include "floatem.h"
  22. #include "fpswa.h"
  23. #include <smbios.h>
  24. extern ULONGLONG PhysicalIOBase;
  25. BOOLEAN
  26. HalpCompareEfiGuid (
  27. IN EFI_GUID CheckGuid,
  28. IN EFI_GUID ReferenceGuid
  29. );
  30. BOOLEAN
  31. MmSetPageProtection(
  32. IN PVOID VirtualAddress,
  33. IN SIZE_T NumberOfBytes,
  34. IN ULONG NewProtect
  35. );
  36. EFI_STATUS
  37. HalpCallEfiPhysical(
  38. IN ULONGLONG Arg1,
  39. IN ULONGLONG Arg2,
  40. IN ULONGLONG Arg3,
  41. IN ULONGLONG Arg4,
  42. IN ULONGLONG Arg5,
  43. IN ULONGLONG Arg6,
  44. IN ULONGLONG EP,
  45. IN ULONGLONG GP
  46. );
  47. EFI_STATUS
  48. HalpCallEfiVirtual(
  49. IN ULONGLONG Arg1,
  50. IN ULONGLONG Arg2,
  51. IN ULONGLONG Arg3,
  52. IN ULONGLONG Arg4,
  53. IN ULONGLONG Arg5,
  54. IN ULONGLONG Arg6,
  55. IN ULONGLONG EP,
  56. IN ULONGLONG GP
  57. );
  58. LONG
  59. HalFpEmulate(
  60. ULONG trap_type,
  61. BUNDLE *pbundle,
  62. ULONGLONG *pipsr,
  63. ULONGLONG *pfpsr,
  64. ULONGLONG *pisr,
  65. ULONGLONG *ppreds,
  66. ULONGLONG *pifs,
  67. FP_STATE *fp_state
  68. );
  69. BOOLEAN
  70. HalEFIFpSwa(
  71. VOID
  72. );
  73. VOID
  74. HalpFpswaPlabelFixup(
  75. EFI_MEMORY_DESCRIPTOR *EfiVirtualMemoryMapPtr,
  76. ULONGLONG MapEntries,
  77. ULONGLONG EfiDescriptorSize,
  78. PPLABEL_DESCRIPTOR PlabelPointer
  79. );
  80. PUCHAR
  81. HalpGetSmBiosVersion (
  82. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  83. );
  84. //
  85. // External global data
  86. //
  87. extern HALP_SAL_PAL_DATA HalpSalPalData;
  88. extern ULONGLONG HalpPalProcPointer;
  89. extern ULONGLONG HalpSalProcPointer;
  90. extern ULONGLONG HalpSalProcGlobalPointer;
  91. extern KSPIN_LOCK HalpSalSpinLock;
  92. extern KSPIN_LOCK HalpSalStateInfoSpinLock;
  93. extern KSPIN_LOCK HalpMcaSpinLock;
  94. extern KSPIN_LOCK HalpInitSpinLock;
  95. extern KSPIN_LOCK HalpCmcSpinLock;
  96. extern KSPIN_LOCK HalpCpeSpinLock;
  97. #define VENDOR_SPECIFIC_GUID \
  98. { 0xa3c72e56, 0x4c35, 0x11d3, 0x8a, 0x03, 0x0, 0xa0, 0xc9, 0x06, 0xad, 0xec }
  99. #define ConfigGuidOffset 0x100
  100. #define ConfigTableOffset 0x200
  101. #define VariableNameOffset 0x100
  102. #define VendorGuidOffset 0x200
  103. #define AttributeOffset 0x300
  104. #define DataSizeOffset 0x400
  105. #define DataBufferOffset 0x500
  106. #define EndOfCommonDataOffset 0x600
  107. //
  108. // Read Variable and Write Variable will not be called till the copying out of
  109. // Memory Descriptors is done. Because the lock is released before copying and we are using
  110. // the same offset for read/write variable as well as memory layout calls.
  111. //
  112. #define MemoryMapSizeOffset 0x100
  113. #define DescriptorSizeOffset 0x200
  114. #define DescriptorVersionOffset 0x300
  115. #define MemoryMapOffset 0x400
  116. #define OptionROMAddress 0xC0000
  117. #define FP_EMUL_ERROR -1
  118. SST_MEMORY_LIST PalCode;
  119. NTSTATUS EfiInitStatus;
  120. ULONGLONG PalTrMask;
  121. PUCHAR HalpConfigGuidVirtualPtr, HalpConfigGuidPhysPtr;
  122. PUCHAR HalpConfigTableVirtualPtr;
  123. PUCHAR HalpConfigTablePhysPtr;
  124. EFI_CONFIGURATION_TABLE *EfiConfigTableVirtualPtr;
  125. EFI_CONFIGURATION_TABLE EfiConfigTable;
  126. EFI_GUID CheckGuid;
  127. EFI_GUID SalGuid = SAL_SYSTEM_TABLE_GUID;
  128. EFI_GUID VendorGuid;
  129. PUCHAR HalpVendorGuidPhysPtr;
  130. PUCHAR HalpVendorGuidVirtualPtr;
  131. EFI_SYSTEM_TABLE *EfiSysTableVirtualPtr;
  132. EFI_SYSTEM_TABLE *EfiSysTableVirtualPtrCpy;
  133. EFI_RUNTIME_SERVICES *EfiRSVirtualPtr;
  134. EFI_BOOT_SERVICES *EfiBootVirtualPtr;
  135. PLABEL_DESCRIPTOR *EfiVirtualGetVariablePtr; // Get Variable
  136. PLABEL_DESCRIPTOR *EfiVirtualGetNextVariableNamePtr; // Get NextVariable Name
  137. PLABEL_DESCRIPTOR *EfiVirtualSetVariablePtr; // Set Variable
  138. PLABEL_DESCRIPTOR *EfiVirtualGetTimePtr; // Get Time
  139. PLABEL_DESCRIPTOR *EfiVirtualSetTimePtr; // Set Time
  140. PLABEL_DESCRIPTOR *EfiSetVirtualAddressMapPtr; // Set Virtual Address Map
  141. PLABEL_DESCRIPTOR *EfiResetSystemPtr; // Reboot
  142. PULONGLONG AttributePtr;
  143. ULONGLONG EfiAttribute;
  144. PULONGLONG DataSizePtr;
  145. ULONGLONG EfiDataSize;
  146. ULONGLONG EfiConfigTableSize, EfiMemoryMapSize,EfiDescriptorSize,EfiMapEntries;
  147. ULONG EfiDescriptorVersion;
  148. PULONGLONG HalpPhysBSPointer;
  149. PULONGLONG HalpPhysStackPointer;
  150. PUCHAR HalpVirtualEfiSalPalDataPointer;
  151. PUCHAR HalpPhysEfiSalPalDataPointer;
  152. PUCHAR HalpVirtualCommonDataPointer;
  153. PUCHAR HalpPhysCommonDataPointer;
  154. PUCHAR HalpVariableNamePhysPtr;
  155. PUCHAR HalpVariableAttributesPhysPtr;
  156. PUCHAR HalpDataSizePhysPtr;
  157. PUCHAR HalpDataPhysPtr;
  158. PUCHAR HalpMemoryMapSizePhysPtr;
  159. PUCHAR HalpMemoryMapPhysPtr;
  160. PUCHAR HalpDescriptorSizePhysPtr;
  161. PUCHAR HalpDescriptorVersionPhysPtr;
  162. PUCHAR HalpVariableNameVirtualPtr;
  163. PUCHAR HalpVariableAttributesVirtualPtr;
  164. PUCHAR HalpDataSizeVirtualPtr;
  165. PUCHAR HalpDataVirtualPtr;
  166. PUCHAR HalpCommonDataEndPtr;
  167. PUCHAR HalpMemoryMapSizeVirtualPtr;
  168. PVOID HalpMemoryMapVirtualPtr;
  169. PUCHAR HalpDescriptorSizeVirtualPtr;
  170. PUCHAR HalpDescriptorVersionVirtualPtr;
  171. EFI_FPSWA HalpFpEmulate;
  172. KSPIN_LOCK EFIMPLock;
  173. ULONG HalpOsBootRendezVector;
  174. BOOLEAN
  175. HalpCompareEfiGuid (
  176. IN EFI_GUID CheckGuid,
  177. IN EFI_GUID ReferenceGuid
  178. )
  179. /*++
  180. --*/
  181. {
  182. USHORT i;
  183. USHORT TotalArrayLength = 8;
  184. if (CheckGuid.Data1 != ReferenceGuid.Data1) {
  185. return FALSE;
  186. } else if (CheckGuid.Data2 != ReferenceGuid.Data2) {
  187. return FALSE;
  188. } else if (CheckGuid.Data3 != ReferenceGuid.Data3) {
  189. return FALSE;
  190. }
  191. for (i = 0; i != TotalArrayLength; i++) {
  192. if (CheckGuid.Data4[i] != ReferenceGuid.Data4[i])
  193. return FALSE;
  194. }
  195. return TRUE;
  196. } // HalpCompareEfiGuid()
  197. VOID
  198. HalpInitSalPalWorkArounds(
  199. VOID
  200. )
  201. /*++
  202. Routine Description:
  203. This function determines and initializes the FW workarounds.
  204. Arguments:
  205. None.
  206. Return Value:
  207. None.
  208. Globals:
  209. Notes: This function is being called at the end of HalpInitSalPal.
  210. It should not access SST members if this SAL table is unmapped.
  211. --*/
  212. {
  213. NTSTATUS status;
  214. extern FADT HalpFixedAcpiDescTable;
  215. #define HalpIsIntelOEM() \
  216. ( !_strnicmp( HalpFixedAcpiDescTable.Header.OEMID, "INTEL", 5 ) )
  217. #define HalpIsBigSur() \
  218. ( !strncmp( HalpFixedAcpiDescTable.Header.OEMTableID, "W460GXBS", 8 ) )
  219. #define HalpIsIntelBigSur() \
  220. ( HalpIsIntelOEM() && HalpIsBigSur() )
  221. if ( HalpIsIntelOEM() ) {
  222. //
  223. // If Intel BigSur and FW build < 103 (checked as Pal_A_Revision < 0x20),
  224. // enable the SAL_GET_STATE_INFO log id increment workaround.
  225. //
  226. if ( HalpIsBigSur() ) {
  227. if ( HalpSalPalData.PalVersion.PAL_A_Revision < 0x20 ) {
  228. HalpSalPalData.Flags |= HALP_SALPAL_FIX_MCE_LOG_ID;
  229. HalpSalPalData.Flags |= HALP_SALPAL_FIX_MP_SAFE;
  230. }
  231. //
  232. // HALP_SALPAL_MCE_MODINFO_CPUINDINFO_OMITTED 04/12/2001:
  233. // FW omits completely ERROR_PROCESSOR.CpuIdInfo field in the log.
  234. // Softsur: This is fixed with developer FW SoftMca3 05/09/2001.
  235. // Lion : ?
  236. //
  237. // HALP_SALPAL_MCE_PROCESSOR_STATICINFO_PARTIAL 04/12/2001:
  238. // FW does not pad invalid processor staticinfo fields.
  239. // We do not know when it is going to be fixed.
  240. //
  241. if ( HalpSalPalData.PalVersion.PAL_A_Revision < 0x21 ) {
  242. HalpSalPalData.Flags |= HALP_SALPAL_MCE_PROCESSOR_CPUIDINFO_OMITTED;
  243. }
  244. HalpSalPalData.Flags |= HALP_SALPAL_MCE_PROCESSOR_STATICINFO_PARTIAL;
  245. }
  246. else {
  247. //
  248. // If Intel Lion and FW build < 78b (checked as SalRevision < 0x300),
  249. // enable the SAL_GET_STATE_INFO log id increment workaround.
  250. //
  251. if ( HalpSalPalData.SalRevision.Revision < 0x300 ) {
  252. HalpSalPalData.Flags |= HALP_SALPAL_FIX_MCE_LOG_ID;
  253. HalpSalPalData.Flags |= HALP_SALPAL_FIX_MP_SAFE;
  254. }
  255. HalpSalPalData.Flags |= HALP_SALPAL_MCE_PROCESSOR_CPUIDINFO_OMITTED;
  256. HalpSalPalData.Flags |= HALP_SALPAL_MCE_PROCESSOR_STATICINFO_PARTIAL;
  257. }
  258. }
  259. return;
  260. } // HalpInitSalPalWorkArounds()
  261. NTSTATUS
  262. HalpInitSalPal(
  263. PLOADER_PARAMETER_BLOCK LoaderBlock
  264. )
  265. /*++
  266. Routine Description:
  267. This function extracts data from the SAL system table, virtually maps the
  268. SAL code, SAL data, and PAL code areas. PAL requires a TR mapping, and
  269. is mapped using an architected TR, using the smallest page size to map
  270. the entire PAL code region. If SAL data or SAL code areas can be mapped in
  271. the same page, it uses the same translation. Otherwise, it uses MmMapIoSpace.
  272. Arguments:
  273. LoaderBlock - Supplies a pointer to the Loader parameter block, containing the
  274. physical address of the SAL system table.
  275. Return Value:
  276. STATUS_SUCCESS is returned if the mappings were successful, and SAL/PAL calls can
  277. be made. Otherwise, STATUS_UNSUCCESSFUL is returned if it cannot virtually map
  278. the areas or if PAL requires a page larger than 16MB.
  279. Assumptions: The EfiSysTableVirtualPtr is initialized prior by EfiInitialization.
  280. --*/
  281. {
  282. //
  283. // Local declarations
  284. //
  285. PSAL_PAL_ENTRY_POINT FwEntry;
  286. PSST_MEMORY_DESCRIPTOR SstMemoryDescriptor;
  287. PAP_WAKEUP_DESCRIPTOR ApWakeupDescriptor;
  288. PVOID NextEntry, FwCodeSpace;
  289. UCHAR Checksum;
  290. PUCHAR CheckBuf;
  291. ULONG index,i,SstLength;
  292. SAL_PAL_RETURN_VALUES RetVals;
  293. PHYSICAL_ADDRESS physicalAddr;
  294. SAL_STATUS SALstatus;
  295. BOOLEAN LargerThan16Mb, MmMappedSalCode, MmMappedSalData;
  296. ULONGLONG physicalEfiST,physicalSST;
  297. ULONGLONG physicalPAL, physicalSAL, physicalSALGP;
  298. ULONGLONG PhysicalConfigPtr;
  299. SST_MEMORY_LIST SalCode,SalData, FwCode;
  300. BOOLEAN FoundSalTable;
  301. ULONGLONG palStatus;
  302. PAL_VERSION_STRUCT minimumPalVersion;
  303. ULONG PalPageShift;
  304. ULONGLONG PalPteUlong;
  305. HalpVirtualEfiSalPalDataPointer = (PUCHAR)(ExAllocatePool (NonPagedPool, PAGE_SIZE));
  306. HalpConfigTableVirtualPtr = HalpVirtualEfiSalPalDataPointer + ConfigTableOffset;
  307. HalpConfigGuidVirtualPtr = HalpVirtualEfiSalPalDataPointer + ConfigGuidOffset;
  308. HalpPhysEfiSalPalDataPointer = (PUCHAR)((MmGetPhysicalAddress(HalpVirtualEfiSalPalDataPointer)).QuadPart);
  309. HalpConfigTablePhysPtr = HalpPhysEfiSalPalDataPointer + ConfigTableOffset;
  310. HalpConfigGuidPhysPtr = HalpPhysEfiSalPalDataPointer + ConfigGuidOffset;
  311. EfiConfigTableVirtualPtr = &EfiConfigTable;
  312. EfiConfigTableSize = (ULONGLONG) sizeof(EFI_CONFIGURATION_TABLE);
  313. HalDebugPrint(( HAL_INFO, "SAL_PAL: Entering HalpInitSalPal\n" ));
  314. FoundSalTable = FALSE;
  315. //
  316. // Extract SST physical address out of EFI table
  317. //
  318. PhysicalConfigPtr = (ULONGLONG) EfiSysTableVirtualPtrCpy -> ConfigurationTable;
  319. for (index = 0; (FoundSalTable == FALSE) && (index <= (EfiSysTableVirtualPtr->NumberOfTableEntries)); index = index + 1) {
  320. physicalAddr.QuadPart = PhysicalConfigPtr;
  321. EfiConfigTableVirtualPtr = MmMapIoSpace(physicalAddr, sizeof(EFI_CONFIGURATION_TABLE),MmCached);
  322. if (EfiConfigTableVirtualPtr == NULL) {
  323. HalDebugPrint(( HAL_ERROR, "SAL_PAL: Efi Config Table Virtual Addr is NULL\n" ));
  324. EfiInitStatus = STATUS_UNSUCCESSFUL;
  325. return STATUS_UNSUCCESSFUL;
  326. }
  327. CheckGuid = EfiConfigTableVirtualPtr -> VendorGuid;
  328. PhysicalConfigPtr = PhysicalConfigPtr + EfiConfigTableSize;
  329. HalDebugPrint(( HAL_INFO,
  330. "SAL_PAL: Found new ConfigPhysPtr 0x%I64x points to tablesize 0x%I64x\n",
  331. PhysicalConfigPtr, EfiConfigTableSize ));
  332. // if (CheckGuid.Data1 == 0xeb9d2d32)
  333. if (HalpCompareEfiGuid(CheckGuid, SalGuid)) {
  334. FoundSalTable = TRUE;
  335. }
  336. }
  337. physicalSST = (ULONGLONG) EfiConfigTableVirtualPtr -> VendorTable;
  338. //
  339. // Zero out internal structures
  340. //
  341. RtlZeroMemory(&HalpSalPalData, sizeof(HalpSalPalData));
  342. RtlZeroMemory(&SalCode, sizeof(SST_MEMORY_LIST));
  343. RtlZeroMemory(&PalCode, sizeof(SST_MEMORY_LIST));
  344. RtlZeroMemory(&SalData, sizeof(SST_MEMORY_LIST));
  345. RtlZeroMemory(&FwCode, sizeof(SST_MEMORY_LIST));
  346. //
  347. // Initialize flags
  348. //
  349. MmMappedSalCode = FALSE;
  350. MmMappedSalData = FALSE;
  351. HalpSalPalData.Status = STATUS_SUCCESS;
  352. //
  353. // Map the SST, get the length of entire SST to remap the rest of it
  354. //
  355. physicalAddr.QuadPart = physicalSST;
  356. HalpSalPalData.SalSystemTable = MmMapIoSpace(physicalAddr,sizeof(SST_HEADER),MmCached);
  357. if (HalpSalPalData.SalSystemTable) {
  358. //
  359. // Save SAL revision in case we decide to unmap it later on.
  360. //
  361. HalpSalPalData.SalRevision.Revision = HalpSalPalData.SalSystemTable->SalRev;
  362. HalDebugPrint(( HAL_INFO,
  363. "SAL_PAL: Found SST SAL v%d.%d (XXTF:%d) at PhysAddr 0x%I64x & mapped to VirtAddr 0x%I64x\n",
  364. HalpSalPalData.SalRevision.Major,
  365. HalpSalPalData.SalRevision.Minor,
  366. HalpSalPalData.SalRevision.Revision,
  367. physicalSST,
  368. HalpSalPalData.SalSystemTable));
  369. SstLength=HalpSalPalData.SalSystemTable->Length;
  370. MmUnmapIoSpace((PVOID)HalpSalPalData.SalSystemTable,sizeof(SST_HEADER));
  371. HalpSalPalData.SalSystemTable = MmMapIoSpace(physicalAddr,SstLength,MmCached);
  372. } else {
  373. HalDebugPrint(( HAL_INFO, "SAL_PAL: Couldn't virtually map SST (PhysAddr: 0x%I64x)\n", physicalSST ));
  374. HalpSalPalData.Status = STATUS_UNSUCCESSFUL;
  375. return STATUS_UNSUCCESSFUL;
  376. }
  377. HalDebugPrint(( HAL_INFO,
  378. "SAL_PAL: Mapped all of SST for PhysAddr 0x%I64x at VirtAddr 0x%I64x for %d bytes\n",
  379. physicalSST,
  380. HalpSalPalData.SalSystemTable, SstLength ));
  381. //
  382. // Because the checksum is maybe not computed and verified by the OS loader before the
  383. // hand-off to the kernel, let's do a checksum and verify it.
  384. //
  385. Checksum=0;
  386. CheckBuf= (PUCHAR) HalpSalPalData.SalSystemTable;
  387. for (i=0; i < SstLength; i++) {
  388. Checksum += CheckBuf[i];
  389. }
  390. if (Checksum) {
  391. HalDebugPrint(( HAL_ERROR, "SAL_PAL: Checksum is BAD with value of %d, should be 0\n", Checksum ));
  392. MmUnmapIoSpace((PVOID)HalpSalPalData.SalSystemTable,SstLength);
  393. HalpSalPalData.Status = STATUS_UNSUCCESSFUL;
  394. return STATUS_UNSUCCESSFUL;
  395. }
  396. HalDebugPrint(( HAL_INFO, "SAL_PAL: Checksum is GOOD\n" ));
  397. //
  398. // Pull out the SAL/PAL entrypoint and memory descriptor information we need by iterating
  399. // over the entire SST.
  400. //
  401. NextEntry = (PUCHAR)(((PUCHAR) HalpSalPalData.SalSystemTable) + sizeof(SST_HEADER));
  402. for (i = 0; i < HalpSalPalData.SalSystemTable->EntryCount; i++) {
  403. switch ( *(PUCHAR)NextEntry ) {
  404. case SAL_PAL_ENTRY_POINT_TYPE:
  405. //
  406. // It is assumed only one Entry Point Type in the SST but we do not currently
  407. // impose this in this code.
  408. //
  409. FwEntry = (PSAL_PAL_ENTRY_POINT)NextEntry;
  410. physicalSAL = FwEntry->SalEntryPoint;
  411. physicalPAL = FwEntry->PalEntryPoint;
  412. physicalSALGP = FwEntry->GlobalPointer;
  413. HalDebugPrint(( HAL_INFO,
  414. "SAL_PAL: SAL_PROC PhysAddr at 0x%I64x\n"
  415. "SAL_PAL: PAL_PROC PhysAddr at 0x%I64x\n"
  416. "SAL_PAL: SAL_GP PhysAddr at 0x%I64x\n",
  417. physicalSAL,
  418. physicalPAL,
  419. physicalSALGP
  420. ));
  421. ((PSAL_PAL_ENTRY_POINT)NextEntry)++;
  422. break;
  423. case SST_MEMORY_DESCRIPTOR_TYPE:
  424. //
  425. // It is assumed only one REGULAR_MEMORY entry for PAL_CODE_MEM, SAL_CODE_MEM and
  426. // SAL_DATA_MEM. However, we do not currently impose this in the code.
  427. //
  428. SstMemoryDescriptor = (PSST_MEMORY_DESCRIPTOR)NextEntry;
  429. HalDebugPrint(( HAL_INFO,
  430. "SAL_PAL: MemDesc for PhysAddr 0x%I64x (%I64d KB) - VaReg:%d,Type:%d,Use:%d\n",
  431. SstMemoryDescriptor->MemoryAddress,(ULONGLONG)SstMemoryDescriptor->Length * 4,
  432. SstMemoryDescriptor->NeedVaReg,SstMemoryDescriptor->MemoryType,SstMemoryDescriptor->MemoryUsage
  433. ));
  434. if (SstMemoryDescriptor->MemoryType == REGULAR_MEMORY) {
  435. switch(SstMemoryDescriptor->MemoryUsage) {
  436. case PAL_CODE_MEM:
  437. PalCode.PhysicalAddress = SstMemoryDescriptor->MemoryAddress;
  438. PalCode.Length = SstMemoryDescriptor->Length << 12;
  439. PalCode.NeedVaReg = SstMemoryDescriptor->NeedVaReg;
  440. break;
  441. case SAL_CODE_MEM:
  442. SalCode.PhysicalAddress = SstMemoryDescriptor->MemoryAddress;
  443. SalCode.Length = SstMemoryDescriptor->Length << 12;
  444. SalCode.NeedVaReg = SstMemoryDescriptor->NeedVaReg;
  445. break;
  446. case SAL_DATA_MEM:
  447. SalData.PhysicalAddress = SstMemoryDescriptor->MemoryAddress;
  448. SalData.Length = SstMemoryDescriptor->Length << 12;
  449. SalData.NeedVaReg = SstMemoryDescriptor->NeedVaReg;
  450. break;
  451. case FW_RESERVED:
  452. // We need to virtually map and count these areas for NVM access.
  453. // We should keep a list of all such regions and would allocate an
  454. // array of virtual address mappings for each NVM region for later
  455. // use when accessing variables.
  456. // No NVM support currently, so ignore for now.
  457. break;
  458. default:
  459. break;
  460. }
  461. } else if ((SstMemoryDescriptor->MemoryType == FIRMWARE_CODE) &&
  462. (SstMemoryDescriptor->MemoryUsage == FW_SAL_PAL)) {
  463. FwCode.PhysicalAddress = SstMemoryDescriptor->MemoryAddress;
  464. FwCode.Length = SstMemoryDescriptor->Length << 12;
  465. FwCode.NeedVaReg = SstMemoryDescriptor->NeedVaReg;
  466. }
  467. ((PSST_MEMORY_DESCRIPTOR)NextEntry)++;
  468. break;
  469. case PLATFORM_FEATURES_TYPE:
  470. // We ignore this entry for now...
  471. ((PPLATFORM_FEATURES)NextEntry)++;
  472. break;
  473. case TRANSLATION_REGISTER_TYPE:
  474. // We ignore this entry for now...
  475. ((PTRANSLATION_REGISTER)NextEntry)++;
  476. break;
  477. case PTC_COHERENCE_DOMAIN_TYPE:
  478. // We ignore this entry for now...
  479. ((PPTC_COHERENCE_DOMAIN)NextEntry)++;
  480. break;
  481. case AP_WAKEUP_DESCRIPTOR_TYPE:
  482. ApWakeupDescriptor = (PAP_WAKEUP_DESCRIPTOR)NextEntry;
  483. HalpOsBootRendezVector = (ULONG) ApWakeupDescriptor->WakeupVector;
  484. if ((HalpOsBootRendezVector < 0x100 ) && (HalpOsBootRendezVector > 0xF)) {
  485. HalDebugPrint(( HAL_INFO, "SAL_PAL: Found Valid WakeupVector: 0x%x\n",
  486. HalpOsBootRendezVector ));
  487. } else {
  488. HalDebugPrint(( HAL_INFO, "SAL_PAL: Invalid WakeupVector.Using Default: 0x%x\n",
  489. DEFAULT_OS_RENDEZ_VECTOR ));
  490. HalpOsBootRendezVector = DEFAULT_OS_RENDEZ_VECTOR;
  491. }
  492. ((PAP_WAKEUP_DESCRIPTOR)NextEntry)++;
  493. break;
  494. default:
  495. HalDebugPrint(( HAL_ERROR,
  496. "SAL_PAL: EntryType %d is bad at VirtAddr 0x%I64x, Aborting\n",
  497. *(PUCHAR)NextEntry,
  498. NextEntry ));
  499. // An unknown SST Type was found, so we can't continue
  500. MmUnmapIoSpace((PVOID)HalpSalPalData.SalSystemTable,SstLength);
  501. HalpSalPalData.Status = STATUS_UNSUCCESSFUL;
  502. return STATUS_UNSUCCESSFUL;
  503. }
  504. }
  505. //
  506. // Initialize the HAL private spinlocks
  507. //
  508. // - HalpSalSpinLock, HalpSalStateInfoSpinLock are used for MP synchronization of the
  509. // SAL calls that are not MP-safe.
  510. // - HalpMcaSpinLock is used for defining an MCA monarch and MP synchrnonization of shared
  511. // HAL MCA resources during OS_MCA calls.
  512. //
  513. KeInitializeSpinLock(&HalpSalSpinLock);
  514. KeInitializeSpinLock(&HalpSalStateInfoSpinLock);
  515. KeInitializeSpinLock(&HalpMcaSpinLock);
  516. KeInitializeSpinLock(&HalpInitSpinLock);
  517. KeInitializeSpinLock(&HalpCmcSpinLock);
  518. KeInitializeSpinLock(&HalpCpeSpinLock);
  519. //
  520. // Unmap the SalSystemTable since we will be mapping all PAL and SAL code, and SAL data area
  521. // which includes SST.
  522. //
  523. // TEMP TEMP TEMP. we are not unmapping
  524. //
  525. // MmUnmapIoSpace((PVOID)HalpSalPalData.SalSystemTable,SstLength);
  526. //
  527. // Make sure we found all of our entries for mapping
  528. //
  529. if (!(SalCode.Length && SalData.Length && PalCode.Length && FwCode.Length)) {
  530. HalDebugPrint(( HAL_ERROR, "SAL_PAL: One or more of the SalCode, SalData, PalCode, or FwCode spaces not in SST\n" ));
  531. HalpSalPalData.Status = STATUS_UNSUCCESSFUL;
  532. return STATUS_UNSUCCESSFUL;
  533. }
  534. //
  535. // Since PAL will need to use only 1 TR, figure out the page size to use for mapping PAL,
  536. // starting at 16KB, and trying 64KB, 256KB, 1MB, 4MB, and 16MB.
  537. //
  538. HalpSalPalData.PalTrSize = SIZE_IN_BYTES_16KB;
  539. PalTrMask = MASK_16KB;
  540. PalPageShift = 14;
  541. LargerThan16Mb = 1;
  542. while (PalTrMask >= MASK_16MB) {
  543. // Check if it entirely fits in the given page
  544. if ( (PalCode.PhysicalAddress + PalCode.Length) <=
  545. ( (PalCode.PhysicalAddress & PalTrMask) + HalpSalPalData.PalTrSize) ) {
  546. LargerThan16Mb = 0;
  547. break;
  548. }
  549. // Try the next page size, incrementing in multiples of 4 from 16KB to 16MB
  550. PalTrMask <<= 2;
  551. HalpSalPalData.PalTrSize <<= 2;
  552. PalPageShift += 2;
  553. }
  554. //
  555. // If PAL requires a page size of larger than 16MB, fail.
  556. //
  557. if (LargerThan16Mb) {
  558. HalDebugPrint(( HAL_ERROR, "SAL_PAL: More than 16MB was required to map PAL" ));
  559. HalpSalPalData.Status = STATUS_UNSUCCESSFUL;
  560. return STATUS_UNSUCCESSFUL;
  561. }
  562. //
  563. // Set the page size aligned address that fits PAL
  564. //
  565. HalpSalPalData.PalTrBase = PalCode.PhysicalAddress & PalTrMask;
  566. HalDebugPrint(( HAL_INFO,
  567. "SAL_PAL: For the PAL code located at 0x%I64x - length 0x%I64x, the TrMask is 0x%I64x and TrSize is %d Kbytes\n",
  568. PalCode.PhysicalAddress,
  569. PalCode.Length,
  570. PalTrMask,
  571. HalpSalPalData.PalTrSize/1024 ));
  572. //
  573. // Map the PAL code at a architected address reserved for SAL/PAL
  574. //
  575. // PAL is known to have an alignment of 256KB.
  576. //
  577. PalCode.VirtualAddress = HAL_PAL_VIRTUAL_ADDRESS + (PalCode.PhysicalAddress - HalpSalPalData.PalTrBase);
  578. //
  579. // Setup the ITR and DTRs to map PAL
  580. //
  581. PalPteUlong = HalpSalPalData.PalTrBase | VALID_KERNEL_EXECUTE_PTE;
  582. KeFillFixedEntryTb((PHARDWARE_PTE)&PalPteUlong,
  583. (PVOID)HAL_PAL_VIRTUAL_ADDRESS,
  584. PalPageShift,
  585. INST_TB_PAL_INDEX);
  586. KeFillFixedEntryTb((PHARDWARE_PTE)&PalPteUlong,
  587. (PVOID)HAL_PAL_VIRTUAL_ADDRESS,
  588. PalPageShift,
  589. DATA_TB_PAL_INDEX);
  590. //
  591. // SAL has no specific virtual mapping translation requirement. It can use TCs to map the
  592. // SAL code regions and the SAL data regions.
  593. // SAL requires virtual address translations for descriptors like PAL code areas (to be able
  594. // to call PAL for SAL), SAL code, SAL data and NVM areas. SAL_UPDATE_PAL requires a virtual
  595. // mapping of the FW ROM area to perform the update. The latter could be done using TCs.
  596. //
  597. // First check if the SAL code fits in the same page as PAL.
  598. // If it does, then use that mapping, otherwise, create a mapping using MmMapIoSpace and
  599. // mark it executable.
  600. //
  601. if ((SalCode.PhysicalAddress >= HalpSalPalData.PalTrBase) &&
  602. ((SalCode.PhysicalAddress + SalCode.Length) <= (HalpSalPalData.PalTrBase + HalpSalPalData.PalTrSize))) {
  603. SalCode.VirtualAddress = HAL_PAL_VIRTUAL_ADDRESS + (SalCode.PhysicalAddress - HalpSalPalData.PalTrBase);
  604. }
  605. else {
  606. physicalAddr.QuadPart = SalCode.PhysicalAddress;
  607. SalCode.VirtualAddress = (ULONGLONG) MmMapIoSpace(physicalAddr, (ULONG)SalCode.Length, MmCached);
  608. if (!SalCode.VirtualAddress) {
  609. HalDebugPrint(( HAL_ERROR, "SAL_PAL: Failed to map the SAL code region\n" ));
  610. goto SalPalCleanup;
  611. }
  612. HalDebugPrint(( HAL_INFO, "SAL_PAL: Starting to mark %d bytes of SAL code executable\n", SalCode.Length ));
  613. //
  614. // Temporarily commented out for Mm bug of clearing the dirty bit.
  615. // We will enable this.
  616. //
  617. // MmSetPageProtection((PVOID)SalCode.VirtualAddress,
  618. // SalCode.Length,
  619. // 0x40 /* PAGE_EXECUTE_READWRITE */);
  620. //
  621. MmMappedSalCode=TRUE;
  622. }
  623. //
  624. // Same check for SAL data:
  625. // Check if the SAL data fits in the same page as PAL.
  626. // If it does, then use that mapping, otherwise, create a mapping using MmMapIoSpace
  627. //
  628. if ((SalData.PhysicalAddress >= HalpSalPalData.PalTrBase) &&
  629. ((SalData.PhysicalAddress + SalData.Length) <= (HalpSalPalData.PalTrBase + HalpSalPalData.PalTrSize))) {
  630. SalData.VirtualAddress = HAL_PAL_VIRTUAL_ADDRESS + (SalData.PhysicalAddress - HalpSalPalData.PalTrBase);
  631. } else {
  632. physicalAddr.QuadPart = SalData.PhysicalAddress;
  633. SalData.VirtualAddress = (ULONGLONG) MmMapIoSpace(physicalAddr, (ULONG)SalData.Length, MmCached);
  634. if (!SalData.VirtualAddress) {
  635. HalDebugPrint(( HAL_ERROR, "SAL_PAL: Failed to map the SAL data region\n" ));
  636. goto SalPalCleanup;
  637. }
  638. MmMappedSalData=TRUE;
  639. }
  640. HalDebugPrint(( HAL_INFO, "SAL_PAL: Mapped SAL code for PhysAddr 0x%I64x at VirtAddr 0x%I64x for %d bytes\n"
  641. "SAL_PAL: Mapped PAL code for PhysAddr 0x%I64x at VirtAddr 0x%I64x for %d bytes\n"
  642. "SAL_PAL: Mapped SAL data for PhysAddr 0x%I64x at VirtAddr 0x%I64x for %d bytes\n",
  643. SalCode.PhysicalAddress, SalCode.VirtualAddress, SalCode.Length,
  644. PalCode.PhysicalAddress, PalCode.VirtualAddress, PalCode.Length,
  645. SalData.PhysicalAddress, SalData.VirtualAddress, SalData.Length
  646. ));
  647. // Store virtual address pointers of SST, SAL_PROC, PAL_PROC, and GP for use later
  648. // (VirtualAddr = VirtualAddrBase + PhysicalOffset) where (PhysicalOffset = physicalAddr - PhysicalBase)
  649. // We are not ensuring SST is within the SAL code area
  650. // ASSERT((physicalSST > SalCode.PhysicalAddress) && (physicalSST < (SalCode.PhysicalAddress + SalCode.Length)));
  651. // HalpSalPalData.SalSystemTable = (PSST_HEADER) (SalCode.VirtualAddress + (physicalSST - SalCode.PhysicalAddress));
  652. HalpSalProcPointer = (ULONGLONG) (SalCode.VirtualAddress + (physicalSAL - SalCode.PhysicalAddress));
  653. HalpSalProcGlobalPointer = (ULONGLONG) (SalCode.VirtualAddress + (physicalSALGP - SalCode.PhysicalAddress));
  654. HalpPalProcPointer = (ULONGLONG) (PalCode.VirtualAddress + (physicalPAL - PalCode.PhysicalAddress));
  655. //
  656. // Go map the firmware code space
  657. //
  658. // SAL_UPDATE_PAL requires a virtual mapping of the ROM area to perform the update.
  659. //
  660. HalDebugPrint(( HAL_INFO, "SAL_PAL: Mapping and Registering Virtual Address of FwCode area\n" ));
  661. physicalAddr.QuadPart = FwCode.PhysicalAddress;
  662. FwCodeSpace = MmMapIoSpace(physicalAddr, (ULONG) FwCode.Length, MmCached);
  663. //
  664. // Get the PAL version.
  665. //
  666. palStatus = HalCallPal(PAL_VERSION,
  667. 0,
  668. 0,
  669. 0,
  670. NULL,
  671. &minimumPalVersion.ReturnValue,
  672. &HalpSalPalData.PalVersion.ReturnValue,
  673. NULL);
  674. if (palStatus != SAL_STATUS_SUCCESS) {
  675. HalDebugPrint(( HAL_ERROR, "SAL_PAL: Get PAL version number failed. Status = d\n" ));
  676. }
  677. //
  678. // Retrieve SmBiosVersion and save the pointer into HalpSalPalData. Note:
  679. // HalpGetSmBiosVersion will allocate a buffer for SmBiosVersion.
  680. //
  681. HalpSalPalData.SmBiosVersion = HalpGetSmBiosVersion(LoaderBlock);
  682. //
  683. // Determine and Initialize HAL private SAL/PAL WorkArounds if any.
  684. //
  685. HalpInitSalPalWorkArounds();
  686. // We completed initialization
  687. HalDebugPrint(( HAL_INFO, "SAL_PAL: Exiting HalpSalPalInitialization with SUCCESS\n" ));
  688. return HalpSalPalData.Status;
  689. // Cleanup the mappings and get out of here...
  690. SalPalCleanup:
  691. if (MmMappedSalData) {
  692. MmUnmapIoSpace((PVOID) SalData.VirtualAddress, (ULONG) SalData.Length);
  693. }
  694. if (MmMappedSalCode) {
  695. MmUnmapIoSpace((PVOID) SalCode.VirtualAddress, (ULONG) SalCode.Length);
  696. }
  697. HalDebugPrint(( HAL_ERROR, "SAL_PAL: Exiting HalpSalPalInitialization with ERROR!!!\n" ));
  698. HalpSalPalData.Status = STATUS_UNSUCCESSFUL;
  699. return HalpSalPalData.Status;
  700. } // HalpInitSalPal()
  701. PUCHAR
  702. HalpGetSmBiosVersion (
  703. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  704. )
  705. /*++
  706. Routine Description:
  707. This function retrieves the SmBiosVersion string from the BIOS structure
  708. table, allocates memory for the buffer, copies the string to the buffer,
  709. and returns a pointer to this buffer. If unsuccessful, this function
  710. returns a NULL.
  711. Arguments:
  712. LoaderBlock - Pointer to the loader parameter block.
  713. Return Value:
  714. Pointer to a buffer that contains SmBiosVersion string.
  715. --*/
  716. {
  717. PSMBIOS_EPS_HEADER SMBiosEPSHeader;
  718. PDMIBIOS_EPS_HEADER DMIBiosEPSHeader;
  719. USHORT SMBiosTableLength;
  720. USHORT SMBiosTableNumberStructures;
  721. PUCHAR SmBiosVersion;
  722. PHYSICAL_ADDRESS SMBiosTablePhysicalAddress;
  723. PUCHAR SMBiosDataVirtualAddress;
  724. UCHAR Type;
  725. UCHAR Length;
  726. UCHAR BiosVersionStringNumber;
  727. UCHAR chr;
  728. USHORT i;
  729. PUCHAR pBuffer;
  730. BOOLEAN Found;
  731. if (LoaderBlock->Extension->Size < sizeof(LOADER_PARAMETER_EXTENSION)) {
  732. HalDebugPrint((HAL_ERROR, "HalpGetSmBiosVersion: Invalid LoaderBlock extension size\n"));
  733. return NULL;
  734. }
  735. SMBiosEPSHeader = (PSMBIOS_EPS_HEADER)LoaderBlock->Extension->SMBiosEPSHeader;
  736. //
  737. // Verify SM Bios Header signature
  738. //
  739. if ((SMBiosEPSHeader == NULL) || (strncmp((PUCHAR)SMBiosEPSHeader, "_SM_", 4) != 0)) {
  740. HalDebugPrint((HAL_ERROR, "HalpGetSmBiosVersion: Invalid SMBiosEPSHeader\n"));
  741. return NULL;
  742. }
  743. DMIBiosEPSHeader = (PDMIBIOS_EPS_HEADER)&SMBiosEPSHeader->Signature2[0];
  744. //
  745. // Verify DMI Bios Header signature
  746. //
  747. if ((DMIBiosEPSHeader == NULL) || (strncmp((PUCHAR)DMIBiosEPSHeader, "_DMI_", 5) != 0)) {
  748. HalDebugPrint((HAL_ERROR, "HalpGetSmBiosVersion: Invalid DMIBiosEPSHeader\n"));
  749. return NULL;
  750. }
  751. SMBiosTablePhysicalAddress.HighPart = 0;
  752. SMBiosTablePhysicalAddress.LowPart = DMIBiosEPSHeader->StructureTableAddress;
  753. SMBiosTableLength = DMIBiosEPSHeader->StructureTableLength;
  754. SMBiosTableNumberStructures = DMIBiosEPSHeader->NumberStructures;
  755. //
  756. // Map SMBiosTable to virtual address
  757. //
  758. SMBiosDataVirtualAddress = MmMapIoSpace(SMBiosTablePhysicalAddress,
  759. SMBiosTableLength,
  760. MmCached
  761. );
  762. if (!SMBiosDataVirtualAddress) {
  763. HalDebugPrint((HAL_ERROR, "HalpGetSmBiosVersion: Failed to map SMBiosTablePhysicalAddress\n"));
  764. return NULL;
  765. }
  766. //
  767. // The Spec doesn't say that SmBios Type 0 structure has to be the first
  768. // structure at this entry point... so we have to traverse through memory
  769. // to find the right one.
  770. //
  771. i = 0;
  772. Found = FALSE;
  773. while (i < SMBiosTableNumberStructures && !Found) {
  774. i++;
  775. Type = (UCHAR)SMBiosDataVirtualAddress[SMBIOS_STRUCT_HEADER_TYPE_FIELD];
  776. if (Type == 0) {
  777. Found = TRUE;
  778. }
  779. else {
  780. //
  781. // Advance to the next structure
  782. //
  783. SMBiosDataVirtualAddress += SMBiosDataVirtualAddress[SMBIOS_STRUCT_HEADER_LENGTH_FIELD];
  784. // Get pass trailing string-list by looking for a double-null
  785. while (*(PUSHORT)SMBiosDataVirtualAddress != 0) {
  786. SMBiosDataVirtualAddress++;
  787. }
  788. SMBiosDataVirtualAddress += 2;
  789. }
  790. }
  791. if (!Found) {
  792. HalDebugPrint((HAL_ERROR, "HalpGetSmBiosVersion: Could not find Type 0 structure\n"));
  793. return NULL;
  794. }
  795. //
  796. // Extract BIOS Version string from the SmBios Type 0 Structure
  797. //
  798. Length = SMBiosDataVirtualAddress[SMBIOS_STRUCT_HEADER_LENGTH_FIELD];
  799. BiosVersionStringNumber = SMBiosDataVirtualAddress[SMBIOS_TYPE0_STRUCT_BIOSVER_FIELD];
  800. //
  801. // Text strings begin right after the formatted portion of the structure.
  802. //
  803. pBuffer = (PUCHAR)&SMBiosDataVirtualAddress[Length];
  804. //
  805. // Get to the beginning of SmBiosVersion string
  806. //
  807. for (i = 0; i < BiosVersionStringNumber - 1; i++) {
  808. do {
  809. chr = *pBuffer;
  810. pBuffer++;
  811. } while (chr != '\0');
  812. }
  813. //
  814. // Allocate memory for SmBiosVersion string and copy content of
  815. // pBuffer to SmBiosVersion.
  816. //
  817. SmBiosVersion = ExAllocatePool(NonPagedPool, strlen(pBuffer)+1);
  818. if (!SmBiosVersion) {
  819. HalDebugPrint((HAL_ERROR, "HalpGetSmBiosVersion: Failed to allocate memory for SmBiosVersion\n"));
  820. return NULL;
  821. }
  822. strcpy(SmBiosVersion, pBuffer);
  823. MmUnmapIoSpace(SMBiosDataVirtualAddress,
  824. SMBiosTableLength
  825. );
  826. return SmBiosVersion;
  827. }
  828. VOID
  829. HalpInitSalPalNonBsp(
  830. VOID
  831. )
  832. /*++
  833. Routine Description:
  834. This function is called for the non-BSP processors to simply set up the same
  835. TR registers that HalpInitSalPal does for the BSP processor.
  836. Arguments:
  837. None
  838. Return Value:
  839. None
  840. --*/
  841. {
  842. ULONG PalPageShift;
  843. ULONGLONG PalPteUlong;
  844. ULONGLONG PalTrSize;
  845. // If we successfully initialized in HalpSalPalInitialization, then set-up the TR
  846. if (!NT_SUCCESS(HalpSalPalData.Status)) {
  847. return;
  848. }
  849. PalTrSize = HalpSalPalData.PalTrSize;
  850. PalPageShift = 14;
  851. while (PalTrSize > ((ULONGLONG)1 << PalPageShift)) {
  852. PalPageShift += 2;
  853. }
  854. PalPteUlong = HalpSalPalData.PalTrBase | VALID_KERNEL_EXECUTE_PTE;
  855. KeFillFixedEntryTb((PHARDWARE_PTE)&PalPteUlong,
  856. (PVOID)HAL_PAL_VIRTUAL_ADDRESS,
  857. PalPageShift,
  858. INST_TB_PAL_INDEX);
  859. KeFillFixedEntryTb((PHARDWARE_PTE)&PalPteUlong,
  860. (PVOID)HAL_PAL_VIRTUAL_ADDRESS,
  861. PalPageShift,
  862. DATA_TB_PAL_INDEX);
  863. } // HalpInitSalPalNonBsp()
  864. NTSTATUS
  865. HalpEfiInitialization(
  866. PLOADER_PARAMETER_BLOCK LoaderBlock
  867. )
  868. /*++
  869. Routine Description:
  870. This function
  871. Arguments:
  872. LoaderBlock - Supplies a pointer to the Loader parameter block, containing the
  873. physical address of the EFI system table.
  874. Return Value:
  875. STATUS_SUCCESS is returned if the mappings were successful, and EFI calls can
  876. be made. Otherwise, STATUS_UNSUCCESSFUL is returned.
  877. --*/
  878. {
  879. //
  880. // Local declarations
  881. //
  882. EFI_MEMORY_DESCRIPTOR *efiMapEntryPtr, *efiVirtualMemoryMapPtr;
  883. EFI_STATUS status;
  884. ULONGLONG index, mapEntries;
  885. ULONGLONG physicalEfiST, physicalEfiMemoryMapPtr, physicalRunTimeServicesPtr;
  886. ULONGLONG physicalEfiGetVariable, physicalEfiGetNextVariableName, physicalEfiSetVariable;
  887. ULONGLONG physicalEfiGetTime, physicalEfiSetTime;
  888. ULONGLONG physicalEfiSetVirtualAddressMap, physicalEfiResetSystem;
  889. PHYSICAL_ADDRESS physicalAddr;
  890. ULONGLONG physicalPlabel_Fpswa;
  891. FPSWA_INTERFACE *interfacePtr;
  892. PVOID tmpPtr;
  893. //
  894. // First, get the physical address of the fpswa entry point PLABEL.
  895. //
  896. if (LoaderBlock->u.Ia64.FpswaInterface != (ULONG_PTR) NULL) {
  897. physicalAddr.QuadPart = LoaderBlock->u.Ia64.FpswaInterface;
  898. interfacePtr = MmMapIoSpace(physicalAddr,
  899. sizeof(FPSWA_INTERFACE),
  900. MmCached
  901. );
  902. if (interfacePtr == NULL) {
  903. HalDebugPrint(( HAL_FATAL_ERROR, "FpswaInterfacePtr is Null. Efi handle not available\n"));
  904. KeBugCheckEx(FP_EMULATION_ERROR, 0, 0, 0, 0);
  905. return STATUS_UNSUCCESSFUL;
  906. }
  907. physicalPlabel_Fpswa = (ULONGLONG)(interfacePtr->Fpswa);
  908. }
  909. else {
  910. HalDebugPrint(( HAL_FATAL_ERROR, "HAL: EFI FpswaInterface is not available\n"));
  911. KeBugCheckEx(FP_EMULATION_ERROR, 0, 0, 0, 0);
  912. return STATUS_UNSUCCESSFUL;
  913. }
  914. physicalEfiST = LoaderBlock->u.Ia64.EfiSystemTable;
  915. physicalAddr.QuadPart = physicalEfiST;
  916. EfiSysTableVirtualPtr = MmMapIoSpace( physicalAddr, sizeof(EFI_SYSTEM_TABLE), MmCached);
  917. if (EfiSysTableVirtualPtr == NULL) {
  918. HalDebugPrint(( HAL_ERROR, "HAL: EfiSystem Table Virtual Addr is NULL\n" ));
  919. EfiInitStatus = STATUS_UNSUCCESSFUL;
  920. return STATUS_UNSUCCESSFUL;
  921. }
  922. EfiSysTableVirtualPtrCpy = EfiSysTableVirtualPtr;
  923. physicalRunTimeServicesPtr = (ULONGLONG) EfiSysTableVirtualPtr->RuntimeServices;
  924. physicalAddr.QuadPart = physicalRunTimeServicesPtr;
  925. EfiRSVirtualPtr = MmMapIoSpace(physicalAddr, sizeof(EFI_RUNTIME_SERVICES),MmCached);
  926. if (EfiRSVirtualPtr == NULL) {
  927. HalDebugPrint(( HAL_ERROR, "HAL: Run Time Table Virtual Addr is NULL\n" ));
  928. EfiInitStatus = STATUS_UNSUCCESSFUL;
  929. return STATUS_UNSUCCESSFUL;
  930. }
  931. EfiMemoryMapSize = LoaderBlock->u.Ia64.EfiMemMapParam.MemoryMapSize;
  932. EfiDescriptorSize = LoaderBlock->u.Ia64.EfiMemMapParam.DescriptorSize;
  933. EfiDescriptorVersion = LoaderBlock->u.Ia64.EfiMemMapParam.DescriptorVersion;
  934. physicalEfiMemoryMapPtr = (ULONGLONG)LoaderBlock->u.Ia64.EfiMemMapParam.MemoryMap;
  935. physicalAddr.QuadPart = physicalEfiMemoryMapPtr;
  936. efiVirtualMemoryMapPtr = MmMapIoSpace (physicalAddr, EfiMemoryMapSize, MmCached);
  937. if (efiVirtualMemoryMapPtr == NULL) {
  938. HalDebugPrint(( HAL_ERROR, "HAL: Virtual Set Memory Map Virtual Addr is NULL\n" ));
  939. EfiInitStatus = STATUS_UNSUCCESSFUL;
  940. return STATUS_UNSUCCESSFUL;
  941. }
  942. //
  943. // #define VENDOR_SPECIFIC_GUID \
  944. // { 0xa3c72e56, 0x4c35, 0x11d3, 0x8a, 0x03, 0x0, 0xa0, 0xc9, 0x06, 0xad, 0xec }
  945. //
  946. VendorGuid.Data1 = 0x8be4df61;
  947. VendorGuid.Data2 = 0x93ca;
  948. VendorGuid.Data3 = 0x11d2;
  949. VendorGuid.Data4[0] = 0xaa;
  950. VendorGuid.Data4[1] = 0x0d;
  951. VendorGuid.Data4[2] = 0x00;
  952. VendorGuid.Data4[3] = 0xe0;
  953. VendorGuid.Data4[4] = 0x98;
  954. VendorGuid.Data4[5] = 0x03;
  955. VendorGuid.Data4[6] = 0x2b;
  956. VendorGuid.Data4[7] = 0x8c;
  957. HalDebugPrint(( HAL_INFO,
  958. "HAL: EFI SystemTable VA = 0x%I64x, PA = 0x%I64x\n"
  959. "HAL: EFI RunTimeServices VA = 0x%I64x, PA = 0x%I64x\n"
  960. "HAL: EFI MemoryMapPtr VA = 0x%I64x, PA = 0x%I64x\n"
  961. "HAL: EFI MemoryMap Size = 0x%I64x\n"
  962. "HAL: EFI Descriptor Size = 0x%I64x\n",
  963. EfiSysTableVirtualPtr,
  964. physicalEfiST,
  965. EfiRSVirtualPtr,
  966. physicalRunTimeServicesPtr,
  967. efiVirtualMemoryMapPtr,
  968. physicalEfiMemoryMapPtr,
  969. EfiMemoryMapSize,
  970. EfiDescriptorSize
  971. ));
  972. // GetVariable
  973. physicalEfiGetVariable = (ULONGLONG) (EfiRSVirtualPtr -> GetVariable);
  974. physicalAddr.QuadPart = physicalEfiGetVariable;
  975. EfiVirtualGetVariablePtr = MmMapIoSpace (physicalAddr, sizeof(PLABEL_DESCRIPTOR), MmCached);
  976. if (EfiVirtualGetVariablePtr == NULL) {
  977. HalDebugPrint(( HAL_ERROR, "HAL: EfiGetVariable Virtual Addr is NULL\n" ));
  978. EfiInitStatus = STATUS_UNSUCCESSFUL;
  979. return STATUS_UNSUCCESSFUL;
  980. }
  981. HalDebugPrint(( HAL_INFO, "HAL: EFI GetVariable VA = 0x%I64x, PA = 0x%I64x\n",
  982. EfiVirtualGetVariablePtr, physicalEfiGetVariable ));
  983. // GetNextVariableName
  984. physicalEfiGetNextVariableName = (ULONGLONG) (EfiRSVirtualPtr -> GetNextVariableName);
  985. physicalAddr.QuadPart = physicalEfiGetNextVariableName;
  986. EfiVirtualGetNextVariableNamePtr = MmMapIoSpace (physicalAddr,sizeof(PLABEL_DESCRIPTOR),MmCached);
  987. if (EfiVirtualGetNextVariableNamePtr == NULL) {
  988. HalDebugPrint(( HAL_ERROR, "HAL: EfiVirtual Get Next Variable Name Ptr Addr is NULL\n" ));
  989. EfiInitStatus = STATUS_UNSUCCESSFUL;
  990. return STATUS_UNSUCCESSFUL;
  991. }
  992. //SetVariable
  993. physicalEfiSetVariable = (ULONGLONG) (EfiRSVirtualPtr -> SetVariable);
  994. physicalAddr.QuadPart = physicalEfiSetVariable;
  995. EfiVirtualSetVariablePtr = MmMapIoSpace (physicalAddr, sizeof(PLABEL_DESCRIPTOR), MmCached);
  996. if (EfiVirtualSetVariablePtr == NULL) {
  997. HalDebugPrint(( HAL_ERROR, "HAL: EfiVariableSetVariable Pointer dr is NULL\n" ));
  998. EfiInitStatus = STATUS_UNSUCCESSFUL;
  999. return STATUS_UNSUCCESSFUL;
  1000. }
  1001. HalDebugPrint(( HAL_INFO, "HAL: EFI Set Variable VA = 0x%I64x, PA = 0x%I64x\n",
  1002. EfiVirtualSetVariablePtr, physicalEfiSetVariable ));
  1003. //GetTime
  1004. physicalEfiGetTime = (ULONGLONG) (EfiRSVirtualPtr -> GetTime);
  1005. physicalAddr.QuadPart = physicalEfiGetTime;
  1006. EfiVirtualGetTimePtr = MmMapIoSpace (physicalAddr, sizeof(PLABEL_DESCRIPTOR), MmCached);
  1007. if (EfiVirtualGetTimePtr == NULL) {
  1008. HalDebugPrint(( HAL_ERROR, "HAL: EfiGetTime Virtual Addr is NULL\n" ));
  1009. EfiInitStatus = STATUS_UNSUCCESSFUL;
  1010. return STATUS_UNSUCCESSFUL;
  1011. }
  1012. HalDebugPrint(( HAL_INFO, "HAL: EFI GetTime VA = 0x%I64x, PA = 0x%I64x\n",
  1013. EfiVirtualGetTimePtr, physicalEfiGetTime ));
  1014. //SetTime
  1015. physicalEfiSetTime = (ULONGLONG) (EfiRSVirtualPtr -> SetTime);
  1016. physicalAddr.QuadPart = physicalEfiSetTime;
  1017. EfiVirtualSetTimePtr = MmMapIoSpace (physicalAddr, sizeof(PLABEL_DESCRIPTOR), MmCached);
  1018. if (EfiVirtualSetTimePtr == NULL) {
  1019. HalDebugPrint(( HAL_ERROR, "HAL: EfiSetTime Virtual Addr is NULL\n" ));
  1020. EfiInitStatus = STATUS_UNSUCCESSFUL;
  1021. return STATUS_UNSUCCESSFUL;
  1022. }
  1023. HalDebugPrint(( HAL_INFO, "HAL: EFI SetTime VA = 0x%I64x, PA = 0x%I64x\n",
  1024. EfiVirtualSetTimePtr, physicalEfiSetTime ));
  1025. //SetVirtualAddressMap
  1026. physicalEfiSetVirtualAddressMap = (ULONGLONG) (EfiRSVirtualPtr -> SetVirtualAddressMap);
  1027. physicalAddr.QuadPart = physicalEfiSetVirtualAddressMap;
  1028. EfiSetVirtualAddressMapPtr = MmMapIoSpace (physicalAddr, sizeof(PLABEL_DESCRIPTOR), MmCached);
  1029. if (EfiSetVirtualAddressMapPtr == NULL) {
  1030. HalDebugPrint(( HAL_ERROR, "HAL: Efi Set VirtualMapPointer Virtual Addr is NULL\n" ));
  1031. EfiInitStatus = STATUS_UNSUCCESSFUL;
  1032. return STATUS_UNSUCCESSFUL;
  1033. }
  1034. HalDebugPrint(( HAL_INFO, "HAL: EFI SetVirtualAddressMap VA = 0x%I64x, PA = 0x%I64x\n",
  1035. EfiSetVirtualAddressMapPtr, physicalEfiSetVirtualAddressMap ));
  1036. //ResetSystem
  1037. physicalEfiResetSystem = (ULONGLONG) (EfiRSVirtualPtr -> ResetSystem);
  1038. physicalAddr.QuadPart = physicalEfiResetSystem;
  1039. EfiResetSystemPtr = MmMapIoSpace (physicalAddr, sizeof(PLABEL_DESCRIPTOR), MmCached);
  1040. if (EfiResetSystemPtr == NULL) {
  1041. HalDebugPrint(( HAL_ERROR,"HAL: Efi Reset System Virtual Addr is NULL\n" ));
  1042. EfiInitStatus = STATUS_UNSUCCESSFUL;
  1043. return STATUS_UNSUCCESSFUL;
  1044. }
  1045. HalDebugPrint(( HAL_INFO, "HAL: EFI ResetSystem VA = 0x%I64x, PA = 0x%I64x\n",
  1046. EfiResetSystemPtr, physicalEfiResetSystem ));
  1047. //
  1048. // Allocate one page for Backing store
  1049. //
  1050. physicalAddr.QuadPart = 0xffffffffffffffffI64;
  1051. tmpPtr = MmAllocateContiguousMemory( PAGE_SIZE, physicalAddr );
  1052. HalpPhysBSPointer = (PULONGLONG)( ( MmGetPhysicalAddress( tmpPtr ) ).QuadPart );
  1053. //
  1054. // Allocate one page for the Stack, then make sure the base pointer
  1055. // is assigned to the high address of this block since the stack
  1056. // grows down.
  1057. //
  1058. tmpPtr = MmAllocateContiguousMemory( PAGE_SIZE, physicalAddr );
  1059. HalpPhysStackPointer = (PULONGLONG)( ( MmGetPhysicalAddress( tmpPtr ) ).QuadPart + PAGE_SIZE - 16);
  1060. HalpVirtualCommonDataPointer = (PUCHAR)(ExAllocatePool (NonPagedPool, PAGE_SIZE));
  1061. HalpVariableNameVirtualPtr = HalpVirtualCommonDataPointer + VariableNameOffset;
  1062. HalpVendorGuidVirtualPtr = HalpVirtualCommonDataPointer + VendorGuidOffset;
  1063. HalpVariableAttributesVirtualPtr = HalpVirtualCommonDataPointer + AttributeOffset;
  1064. HalpDataSizeVirtualPtr = HalpVirtualCommonDataPointer + DataSizeOffset;
  1065. HalpDataVirtualPtr = HalpVirtualCommonDataPointer + DataBufferOffset;
  1066. HalpCommonDataEndPtr = HalpVirtualCommonDataPointer + EndOfCommonDataOffset;
  1067. HalpMemoryMapSizeVirtualPtr = HalpVirtualCommonDataPointer + MemoryMapSizeOffset;
  1068. HalpMemoryMapVirtualPtr = (PUCHAR)(HalpVirtualCommonDataPointer + MemoryMapOffset);
  1069. HalpDescriptorSizeVirtualPtr = HalpVirtualCommonDataPointer + DescriptorSizeOffset;
  1070. HalpDescriptorVersionVirtualPtr = HalpVirtualCommonDataPointer + DescriptorVersionOffset;
  1071. HalpPhysCommonDataPointer = (PUCHAR)((MmGetPhysicalAddress(HalpVirtualCommonDataPointer)).QuadPart);
  1072. HalpVariableNamePhysPtr = HalpPhysCommonDataPointer + VariableNameOffset;
  1073. HalpVendorGuidPhysPtr = HalpPhysCommonDataPointer + VendorGuidOffset;
  1074. HalpVariableAttributesPhysPtr = HalpPhysCommonDataPointer + AttributeOffset;
  1075. HalpDataSizePhysPtr = HalpPhysCommonDataPointer + DataSizeOffset;
  1076. HalpDataPhysPtr = HalpPhysCommonDataPointer + DataBufferOffset;
  1077. HalpMemoryMapSizePhysPtr = HalpPhysCommonDataPointer + MemoryMapSizeOffset;
  1078. HalpMemoryMapPhysPtr = HalpPhysCommonDataPointer + MemoryMapOffset;
  1079. HalpDescriptorSizePhysPtr = HalpPhysCommonDataPointer + DescriptorSizeOffset;
  1080. HalpDescriptorVersionPhysPtr = HalpPhysCommonDataPointer + DescriptorVersionOffset;
  1081. AttributePtr = &EfiAttribute;
  1082. DataSizePtr = &EfiDataSize;
  1083. RtlCopyMemory ((PULONGLONG)HalpMemoryMapVirtualPtr,
  1084. efiVirtualMemoryMapPtr,
  1085. (ULONG)(EfiMemoryMapSize)
  1086. );
  1087. //
  1088. // Now, extract SAL, PAL information from the loader parameter block and
  1089. // initializes HAL SAL, PAL definitions.
  1090. //
  1091. // N.B 10/2000:
  1092. // We do not check the return status of HalpInitSalPal(). We should. FIXFIX.
  1093. // In case of failure, we currently flag HalpSalPalData.Status as unsuccessful.
  1094. //
  1095. HalpInitSalPal(LoaderBlock);
  1096. //
  1097. // Initialize Spin Lock
  1098. //
  1099. KeInitializeSpinLock(&EFIMPLock);
  1100. ASSERT (EfiDescriptorVersion == EFI_MEMORY_DESCRIPTOR_VERSION);
  1101. // if (EfiDescriptorVersion != EFI_MEMORY_DESCRIPTION_VERSION) {
  1102. // HalDebugPrint(HAL_ERROR,("Efi Memory Map Pointer VAddr is NULL\n"));
  1103. // EfiInitStatus = STATUS_UNSUCCESSFUL;
  1104. // return STATUS_UNSUCCESSFUL;
  1105. // }
  1106. HalDebugPrint(( HAL_INFO, "HAL: Creating EFI virtual address mapping\n" ));
  1107. efiMapEntryPtr = efiVirtualMemoryMapPtr;
  1108. if (efiMapEntryPtr == NULL) {
  1109. HalDebugPrint(( HAL_ERROR, "HAL: Efi Memory Map Pointer VAddr is NULL\n" ));
  1110. EfiInitStatus = STATUS_UNSUCCESSFUL;
  1111. return STATUS_UNSUCCESSFUL;
  1112. }
  1113. mapEntries = EfiMemoryMapSize/EfiDescriptorSize;
  1114. HalDebugPrint(( HAL_INFO, "HAL: EfiMemoryMapSize: 0x%I64x & EfiDescriptorSize: 0x%I64x & #of entries: 0x%I64x\n",
  1115. EfiMemoryMapSize,
  1116. EfiDescriptorSize,
  1117. mapEntries ));
  1118. HalDebugPrint(( HAL_INFO, "HAL: Efi RunTime Attribute will be printed as 1\n" ));
  1119. for (index = 0; index < mapEntries; index= index + 1) {
  1120. BOOLEAN attribute = 0;
  1121. physicalAddr.QuadPart = efiMapEntryPtr -> PhysicalStart;
  1122. if ((efiMapEntryPtr->Attribute) & EFI_MEMORY_RUNTIME) {
  1123. attribute = 1;
  1124. switch (efiMapEntryPtr->Type) {
  1125. case EfiRuntimeServicesData:
  1126. case EfiReservedMemoryType:
  1127. efiMapEntryPtr->VirtualStart = (ULONGLONG) (MmMapIoSpace (physicalAddr,
  1128. (SIZE_T)((EFI_PAGE_SIZE)*(efiMapEntryPtr->NumberOfPages)),
  1129. (efiMapEntryPtr->Attribute & EFI_MEMORY_WB) ? MmCached : MmNonCached
  1130. ));
  1131. if ((efiMapEntryPtr->VirtualStart) == 0) {
  1132. HalDebugPrint(( HAL_ERROR, "HAL: Efi RunTimeSrvceData/RsrvdMemory area VAddr is NULL\n" ));
  1133. EfiInitStatus = STATUS_UNSUCCESSFUL;
  1134. return STATUS_UNSUCCESSFUL;
  1135. }
  1136. HalDebugPrint(( HAL_INFO,
  1137. "HAL: Efi attribute %d & Type 0x%I64x with # of 4k pages 0x%I64x at PA 0x%I64x & mapped to VA 0x%I64x\n",
  1138. attribute,
  1139. efiMapEntryPtr->Type,
  1140. efiMapEntryPtr->NumberOfPages,
  1141. efiMapEntryPtr->PhysicalStart,
  1142. efiMapEntryPtr->VirtualStart ));
  1143. break;
  1144. case EfiPalCode:
  1145. efiMapEntryPtr->VirtualStart = PalCode.VirtualAddress;
  1146. HalDebugPrint(( HAL_INFO,
  1147. "HAL: Efi attribute %d & Type 0x%I64x with # of 4K pages 0x%I64x at PA 0x%I64x & mapped to VA 0x%I64x\n",
  1148. attribute,
  1149. efiMapEntryPtr->Type,
  1150. efiMapEntryPtr->NumberOfPages,
  1151. efiMapEntryPtr->PhysicalStart,
  1152. efiMapEntryPtr->VirtualStart ));
  1153. break;
  1154. case EfiRuntimeServicesCode:
  1155. if(physicalAddr.QuadPart != OptionROMAddress) {
  1156. efiMapEntryPtr->VirtualStart = (ULONGLONG) (MmMapIoSpace (physicalAddr,
  1157. (EFI_PAGE_SIZE) * (efiMapEntryPtr->NumberOfPages),
  1158. MmCached
  1159. ));
  1160. if ((efiMapEntryPtr->VirtualStart) == 0) {
  1161. HalDebugPrint(( HAL_ERROR, "HAL: Efi RunTimeSrvceCode area VAddr is NULL\n" ));
  1162. EfiInitStatus = STATUS_UNSUCCESSFUL;
  1163. return STATUS_UNSUCCESSFUL;
  1164. }
  1165. //
  1166. // Give Execution previlege
  1167. //
  1168. //
  1169. // Temporarily commented out. Will be enabled once Mm does not clear dirty bit here.
  1170. //
  1171. // MmSetPageProtection ((PVOID)(efiMapEntryPtr->VirtualStart),
  1172. // (EFI_PAGE_SIZE) * (efiMapEntryPtr->NumberOfPages),
  1173. // 0x40 /* PAGE_EXECUTE_READWRITE */
  1174. // );
  1175. HalDebugPrint(( HAL_INFO,
  1176. "HAL: Efi attribute %d & Type 0x%I64x with # of 4K pages 0x%I64x at PA 0x%I64x & mapped to VA 0x%I64x\n",
  1177. attribute,
  1178. efiMapEntryPtr->Type,
  1179. efiMapEntryPtr->NumberOfPages,
  1180. efiMapEntryPtr->PhysicalStart,
  1181. efiMapEntryPtr->VirtualStart));
  1182. break;
  1183. } else {
  1184. efiMapEntryPtr->VirtualStart = OptionROMAddress;
  1185. HalDebugPrint(( HAL_INFO,
  1186. "HAL: Efi attribute %d & Type 0x%I64x with # of 4K pages 0x%I64x at PA 0x%I64x. NOT MAPPED\n",
  1187. attribute,
  1188. efiMapEntryPtr->Type,
  1189. efiMapEntryPtr->NumberOfPages,
  1190. efiMapEntryPtr->PhysicalStart ));
  1191. break;
  1192. }
  1193. case EfiMemoryMappedIO:
  1194. efiMapEntryPtr->VirtualStart = (ULONGLONG) (MmMapIoSpace (physicalAddr,
  1195. (EFI_PAGE_SIZE) * (efiMapEntryPtr->NumberOfPages),
  1196. MmNonCached
  1197. ));
  1198. if ((efiMapEntryPtr->VirtualStart) == 0) {
  1199. HalDebugPrint(( HAL_ERROR, "HAL: Efi MemoryMappedIO VAddr is NULL\n" ));
  1200. EfiInitStatus = STATUS_UNSUCCESSFUL;
  1201. return STATUS_UNSUCCESSFUL;
  1202. }
  1203. HalDebugPrint(( HAL_INFO,
  1204. "HAL: Efi attribute %d & Type 0x%I64x with # of 4K pages 0x%I64x at PA 0x%I64x & mapped to VA 0x%I64x\n",
  1205. attribute,
  1206. efiMapEntryPtr->Type,
  1207. efiMapEntryPtr->NumberOfPages,
  1208. efiMapEntryPtr->PhysicalStart,
  1209. efiMapEntryPtr->VirtualStart ));
  1210. break;
  1211. case EfiMemoryMappedIOPortSpace:
  1212. efiMapEntryPtr->VirtualStart = VIRTUAL_IO_BASE;
  1213. HalDebugPrint(( HAL_INFO,
  1214. "HAL: Efi attribute %d & Type 0x%I64x with # of 4K pages 0x%I64x at PA 0x%I64x ALREADY mapped to VA 0x%I64x\n",
  1215. attribute,
  1216. efiMapEntryPtr->Type,
  1217. efiMapEntryPtr->NumberOfPages,
  1218. efiMapEntryPtr->PhysicalStart,
  1219. efiMapEntryPtr->VirtualStart ));
  1220. break;
  1221. default:
  1222. HalDebugPrint(( HAL_INFO, "HAL: Efi CONTROL SHOULD NOT COME HERE \n" ));
  1223. EfiInitStatus = STATUS_UNSUCCESSFUL;
  1224. return STATUS_UNSUCCESSFUL;
  1225. break;
  1226. }
  1227. } else {
  1228. HalDebugPrint(( HAL_INFO,
  1229. "HAL: Efi attribute %d & Type 0x%I64x with # of 4K pages 0x%I64x at PA 0x%I64x ALREADY mapped to VA 0x%I64x\n",
  1230. attribute,
  1231. efiMapEntryPtr->Type,
  1232. efiMapEntryPtr->NumberOfPages,
  1233. efiMapEntryPtr->PhysicalStart,
  1234. efiMapEntryPtr->VirtualStart ));
  1235. }
  1236. efiMapEntryPtr = NextMemoryDescriptor(efiMapEntryPtr,EfiDescriptorSize);
  1237. }
  1238. status = HalpCallEfi(EFI_SET_VIRTUAL_ADDRESS_MAP_INDEX,
  1239. (ULONGLONG)EfiMemoryMapSize,
  1240. (ULONGLONG)EfiDescriptorSize,
  1241. (ULONGLONG)EfiDescriptorVersion,
  1242. (ULONGLONG)efiVirtualMemoryMapPtr,
  1243. 0,
  1244. 0,
  1245. 0,
  1246. 0
  1247. );
  1248. HalDebugPrint(( HAL_INFO, "HAL: Returned from SetVirtualAddressMap: 0x%Ix\n", status ));
  1249. if (EFI_ERROR( status )) {
  1250. EfiInitStatus = STATUS_UNSUCCESSFUL;
  1251. return STATUS_UNSUCCESSFUL;
  1252. }
  1253. HalDebugPrint(( HAL_INFO, "HAL: EFI Virtual Address mapping done...\n" ));
  1254. EfiInitStatus = STATUS_SUCCESS;
  1255. //
  1256. // Execute some validity checks on the floating point software assist.
  1257. //
  1258. if (LoaderBlock->u.Ia64.FpswaInterface != (ULONG_PTR) NULL) {
  1259. PPLABEL_DESCRIPTOR plabelPointer;
  1260. HalpFpEmulate = interfacePtr->Fpswa;
  1261. if (HalpFpEmulate == NULL ) {
  1262. HalDebugPrint(( HAL_FATAL_ERROR, "HAL: EfiFpswa Virtual Addr is NULL\n" ));
  1263. KeBugCheckEx(FP_EMULATION_ERROR, 0, 0, 0, 0);
  1264. EfiInitStatus = STATUS_UNSUCCESSFUL;
  1265. return STATUS_UNSUCCESSFUL;
  1266. }
  1267. plabelPointer = (PPLABEL_DESCRIPTOR) HalpFpEmulate;
  1268. if ((plabelPointer->EntryPoint & 0xe000000000000000) == 0) {
  1269. HalDebugPrint(( HAL_FATAL_ERROR, "HAL: EfiFpswa Instruction Addr is bougus\n" ));
  1270. KeBugCheckEx(FP_EMULATION_ERROR, 0, 0, 0, 0);
  1271. }
  1272. }
  1273. return STATUS_SUCCESS;
  1274. } // HalpEfiInitialization()
  1275. EFI_STATUS
  1276. HalpCallEfi(
  1277. IN ULONGLONG FunctionId,
  1278. IN ULONGLONG Arg1,
  1279. IN ULONGLONG Arg2,
  1280. IN ULONGLONG Arg3,
  1281. IN ULONGLONG Arg4,
  1282. IN ULONGLONG Arg5,
  1283. IN ULONGLONG Arg6,
  1284. IN ULONGLONG Arg7,
  1285. IN ULONGLONG Arg8
  1286. )
  1287. /*++
  1288. Routine Description:
  1289. :9
  1290. This function is a wrapper function for making a EFI call. Callers within the
  1291. HAL must use this function to call the EFI.
  1292. Arguments:
  1293. FunctionId - The EFI function
  1294. Arg1-Arg7 - EFI defined arguments for each call
  1295. ReturnValues - A pointer to an array of 4 64-bit return values
  1296. Return Value:
  1297. SAL's return status, return value 0, is returned in addition to the ReturnValues structure
  1298. being filled
  1299. --*/
  1300. {
  1301. ULONGLONG EP, GP;
  1302. EFI_STATUS efiStatus;
  1303. //
  1304. // Storage for old level
  1305. //
  1306. KIRQL OldLevel;
  1307. if (((FunctionId != EFI_SET_VIRTUAL_ADDRESS_MAP_INDEX) || (FunctionId != EFI_RESET_SYSTEM_INDEX))
  1308. && (!NT_SUCCESS(EfiInitStatus))) {
  1309. return EFI_UNSUPPORTED;
  1310. }
  1311. switch (FunctionId) {
  1312. case EFI_GET_VARIABLE_INDEX:
  1313. //
  1314. // Dereference the pointer to get the function arguements
  1315. //
  1316. EP = ((PPLABEL_DESCRIPTOR)EfiVirtualGetVariablePtr) -> EntryPoint;
  1317. GP = ((PPLABEL_DESCRIPTOR)EfiVirtualGetVariablePtr) -> GlobalPointer;
  1318. //
  1319. // Acquire MP Lock
  1320. //
  1321. KeAcquireSpinLock (&EFIMPLock, &OldLevel);
  1322. efiStatus = (HalpCallEfiVirtual( (ULONGLONG)Arg1, // VariableNamePtr
  1323. (ULONGLONG)Arg2, // VendorGuidPtr
  1324. (ULONGLONG)Arg3, // VariableAttributesPtr,
  1325. (ULONGLONG)Arg4, // DataSizePtr,
  1326. (ULONGLONG)Arg5, // DataPtr,
  1327. Arg6,
  1328. EP,
  1329. GP
  1330. ));
  1331. //
  1332. // Release the MP Lock
  1333. //
  1334. KeReleaseSpinLock (&EFIMPLock, OldLevel);
  1335. break;
  1336. case EFI_SET_VARIABLE_INDEX:
  1337. //
  1338. // Dereference the pointer to get the function arguements
  1339. //
  1340. EP = ((PPLABEL_DESCRIPTOR)EfiVirtualSetVariablePtr) -> EntryPoint;
  1341. GP = ((PPLABEL_DESCRIPTOR)EfiVirtualSetVariablePtr) -> GlobalPointer;
  1342. //
  1343. // Acquire MP Lock
  1344. //
  1345. KeAcquireSpinLock (&EFIMPLock, &OldLevel);
  1346. efiStatus = (HalpCallEfiVirtual( Arg1,
  1347. Arg2,
  1348. Arg3,
  1349. Arg4,
  1350. Arg5,
  1351. Arg6,
  1352. EP,
  1353. GP
  1354. ));
  1355. //
  1356. // Release the MP Lock
  1357. //
  1358. KeReleaseSpinLock (&EFIMPLock, OldLevel);
  1359. break;
  1360. case EFI_GET_NEXT_VARIABLE_NAME_INDEX:
  1361. //
  1362. // Dereference the pointer to get the function arguements
  1363. //
  1364. EP = ((PPLABEL_DESCRIPTOR)EfiVirtualGetNextVariableNamePtr) -> EntryPoint;
  1365. GP = ((PPLABEL_DESCRIPTOR)EfiVirtualGetNextVariableNamePtr) -> GlobalPointer;
  1366. //
  1367. // Acquire MP Lock
  1368. //
  1369. KeAcquireSpinLock (&EFIMPLock, &OldLevel);
  1370. efiStatus = (HalpCallEfiVirtual( Arg1,
  1371. Arg2,
  1372. Arg3,
  1373. Arg4,
  1374. Arg5,
  1375. Arg6,
  1376. EP,
  1377. GP
  1378. ));
  1379. //
  1380. // Release the MP Lock
  1381. //
  1382. KeReleaseSpinLock (&EFIMPLock, OldLevel);
  1383. break;
  1384. case EFI_GET_TIME_INDEX:
  1385. //
  1386. // Dereference the pointer to get the function arguements
  1387. //
  1388. EP = ((PPLABEL_DESCRIPTOR)EfiVirtualGetTimePtr) -> EntryPoint;
  1389. GP = ((PPLABEL_DESCRIPTOR)EfiVirtualGetTimePtr) -> GlobalPointer;
  1390. //
  1391. // Acquire MP Lock
  1392. //
  1393. KeAcquireSpinLock (&EFIMPLock, &OldLevel);
  1394. efiStatus = (HalpCallEfiVirtual ((ULONGLONG)Arg1, //EFI_TIME
  1395. (ULONGLONG)Arg2, //EFI_TIME Capabilities
  1396. Arg3,
  1397. Arg4,
  1398. Arg5,
  1399. Arg6,
  1400. EP,
  1401. GP
  1402. ));
  1403. //
  1404. // Release the MP Lock
  1405. //
  1406. KeReleaseSpinLock (&EFIMPLock, OldLevel);
  1407. break;
  1408. case EFI_SET_TIME_INDEX:
  1409. //
  1410. // Dereference the pointer to get the function arguements
  1411. //
  1412. EP = ((PPLABEL_DESCRIPTOR)EfiVirtualSetTimePtr) -> EntryPoint;
  1413. GP = ((PPLABEL_DESCRIPTOR)EfiVirtualSetTimePtr) -> GlobalPointer;
  1414. //
  1415. // Acquire MP Lock
  1416. //
  1417. KeAcquireSpinLock (&EFIMPLock, &OldLevel);
  1418. efiStatus = (HalpCallEfiVirtual ((ULONGLONG)Arg1, //EFI_TIME
  1419. Arg2,
  1420. Arg3,
  1421. Arg4,
  1422. Arg5,
  1423. Arg6,
  1424. EP,
  1425. GP
  1426. ));
  1427. //
  1428. // Release the MP Lock
  1429. //
  1430. KeReleaseSpinLock (&EFIMPLock, OldLevel);
  1431. break;
  1432. case EFI_SET_VIRTUAL_ADDRESS_MAP_INDEX:
  1433. //
  1434. // Dereference the pointer to get the function arguements
  1435. //
  1436. EP = ((PPLABEL_DESCRIPTOR)EfiSetVirtualAddressMapPtr) -> EntryPoint;
  1437. GP = ((PPLABEL_DESCRIPTOR)EfiSetVirtualAddressMapPtr) -> GlobalPointer;
  1438. //
  1439. // Arg 1 and 5 are virtual mode pointers. We need to convert to physical
  1440. //
  1441. RtlCopyMemory (HalpMemoryMapVirtualPtr,
  1442. (PULONGLONG)Arg4,
  1443. (ULONG)EfiMemoryMapSize
  1444. );
  1445. //
  1446. // Acquire MP Lock
  1447. //
  1448. KeAcquireSpinLock (&EFIMPLock, &OldLevel);
  1449. efiStatus = (HalpCallEfiPhysical ((ULONGLONG)EfiMemoryMapSize,
  1450. (ULONGLONG)EfiDescriptorSize,
  1451. (ULONGLONG)EfiDescriptorVersion,
  1452. (ULONGLONG)HalpMemoryMapPhysPtr,
  1453. Arg5,
  1454. Arg6,
  1455. EP,
  1456. GP
  1457. ));
  1458. //
  1459. // Release the MP Lock
  1460. //
  1461. KeReleaseSpinLock (&EFIMPLock, OldLevel);
  1462. break;
  1463. case EFI_RESET_SYSTEM_INDEX:
  1464. //
  1465. // Dereference the pointer to get the function arguements
  1466. //
  1467. EP = ((PPLABEL_DESCRIPTOR)EfiResetSystemPtr) -> EntryPoint;
  1468. GP = ((PPLABEL_DESCRIPTOR)EfiResetSystemPtr) -> GlobalPointer;
  1469. //
  1470. // Acquire MP Lock
  1471. //
  1472. KeAcquireSpinLock (&EFIMPLock, &OldLevel);
  1473. efiStatus = ((HalpCallEfiVirtual ( Arg1,
  1474. Arg2,
  1475. Arg3,
  1476. Arg4,
  1477. Arg5,
  1478. Arg6,
  1479. EP,
  1480. GP
  1481. )));
  1482. //
  1483. // Release the MP Lock
  1484. //
  1485. KeReleaseSpinLock (&EFIMPLock, OldLevel);
  1486. break;
  1487. default:
  1488. //
  1489. // DebugPrint("EFI: Not supported now\n");
  1490. //
  1491. efiStatus = EFI_UNSUPPORTED;
  1492. break;
  1493. }
  1494. return efiStatus;
  1495. } // HalpCallEfi()
  1496. HalpFpErrorPrint (PAL_RETURN pal_ret)
  1497. {
  1498. EM_uint64_t err_nr;
  1499. unsigned int qp;
  1500. EM_uint64_t OpCode;
  1501. unsigned int rc;
  1502. unsigned int significand_size;
  1503. unsigned int ISRlow;
  1504. unsigned int f1;
  1505. unsigned int sign;
  1506. unsigned int exponent;
  1507. EM_uint64_t significand;
  1508. unsigned int new_trap_type;
  1509. err_nr = pal_ret.err1 >> 56;
  1510. switch (err_nr) {
  1511. case 1:
  1512. // err_nr = 1 in err1, bits 63-56
  1513. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: template FXX is invalid\n"));
  1514. break;
  1515. case 2:
  1516. // err_nr = 2 in err1, bits 63-56
  1517. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: instruction slot 3 is not valid \n"));
  1518. break;
  1519. case 3:
  1520. // err_nr = 3 in err1, bits 63-56
  1521. // qp in err1, bits 31-0
  1522. qp = (unsigned int) pal_ret.err1 & 0xffffffff;
  1523. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: qualifying predicate PR[%ud] = 0 \n",qp));
  1524. break;
  1525. case 4:
  1526. // err_nr = 4 in err1, bits 63-56
  1527. // OpCode in err2, bits 63-0
  1528. OpCode = pal_ret.err2;
  1529. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: instruction opcode %8x%8x not recognized \n",
  1530. (unsigned int)((OpCode >> 32) & 0xffffffff),(unsigned int)(OpCode & 0xffffffff)));
  1531. break;
  1532. case 5:
  1533. // err_nr = 5 in err1, bits 63-56
  1534. // rc in err1, bits 31-0 (1-0)
  1535. rc = (unsigned int) pal_ret.err1 & 0xffffffff;
  1536. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: invalid rc = %ud\n", rc));
  1537. break;
  1538. case 6:
  1539. // err_nr = 6 in err1, bits 63-56
  1540. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: cannot determine the computation model \n"));
  1541. break;
  1542. case 7:
  1543. // err_nr = 7 in err1, bits 63-56
  1544. // significand_size in err1, bits 55-32
  1545. // ISRlow in err1, bits 31-0
  1546. // f1 in err2, bits 63-32
  1547. // tmp_fp.sign in err2, bit 17
  1548. // tmp_fp.exponent in err2, bits 16-0
  1549. // tmp_fp.significand in err3
  1550. significand_size = (unsigned int)((pal_ret.err1 >> 32) & 0xffffff);
  1551. ISRlow = (unsigned int) (pal_ret.err1 & 0xffffffff);
  1552. f1 = (unsigned int) ((pal_ret.err2 >> 32) & 0xffffffff);
  1553. sign = (unsigned int) ((pal_ret.err2 >> 17) & 0x01);
  1554. exponent = (unsigned int) (pal_ret.err2 & 0x1ffff);
  1555. significand = pal_ret.err3;
  1556. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: incorrect significand \
  1557. size %ud for ISRlow = %4.4x and FR[%ud] = %1.1x %5.5x %8x%8x\n",
  1558. significand_size, ISRlow, f1, sign, exponent,
  1559. (unsigned int)((significand >> 32) & 0xffffffff),
  1560. (unsigned int)(significand & 0xffffffff)));
  1561. break;
  1562. case 8:
  1563. // err_nr = 8 in err1, bits 63-56
  1564. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: non-tiny result\n"));
  1565. break;
  1566. case 9:
  1567. // err_nr = 9 in err1, bits 63-56
  1568. // significand_size in err1, bits 31-0
  1569. significand_size = (unsigned int) pal_ret.err1 & 0xffffffff;
  1570. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: incorrect significand \
  1571. size %ud\n", significand_size));
  1572. break;
  1573. case 10:
  1574. // err_nr = 10 in err1, bits 63-56
  1575. // rc in err1, bits 31-0
  1576. rc = (unsigned int) (pal_ret.err1 & 0xffffffff);
  1577. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: invalid rc = %ud for \
  1578. non-SIMD F1 instruction\n", rc));
  1579. break;
  1580. case 11:
  1581. // err_nr = 11 in err1, bits 63-56
  1582. // ISRlow & 0x0ffff in err1, bits 31-0
  1583. ISRlow = (unsigned int) (pal_ret.err1 & 0xffffffff);
  1584. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: SWA trap code invoked \
  1585. with F1 instruction, w/o O or U set in ISR.code = %x\n", ISRlow));
  1586. break;
  1587. case 12:
  1588. // err_nr = 12 in err1, bits 63-56
  1589. // ISRlow & 0x0ffff in err1, bits 31-0
  1590. ISRlow = (unsigned int) (pal_ret.err1 & 0xffffffff);
  1591. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: SWA trap code invoked \
  1592. with SIMD F1 instruction, w/o O or U set in ISR.code = %x\n", ISRlow));
  1593. break;
  1594. case 13:
  1595. // err_nr = 13 in err1, bits 63-56
  1596. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: non-tiny result low\n"));
  1597. break;
  1598. case 14:
  1599. // err_nr = 14 in err1, bits 63-56
  1600. // rc in err1, bits 31-0
  1601. rc = (unsigned int) (pal_ret.err1 & 0xffffffff);
  1602. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: invalid rc = %ud for \
  1603. SIMD F1 instruction\n", rc));
  1604. break;
  1605. case 15:
  1606. // err_nr = 15 in err1, bits 63-56
  1607. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: non-tiny result high\n"));
  1608. break;
  1609. case 16:
  1610. // err_nr = 16 in err1, bits 63-56
  1611. // OpCode in err2, bits 63-0
  1612. OpCode = pal_ret.err2;
  1613. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: instruction opcode %8x%8x \
  1614. not valid for SWA trap\n", (unsigned int)((OpCode >> 32) & 0xffffffff),
  1615. (unsigned int)(OpCode & 0xffffffff)));
  1616. break;
  1617. case 17:
  1618. // err_nr = 17 in err1, bits 63-56
  1619. // OpCode in err2, bits 63-0
  1620. // ISRlow in err3, bits 31-0
  1621. OpCode = pal_ret.err2;
  1622. ISRlow = (unsigned int) (pal_ret.err3 & 0xffffffff);
  1623. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: fp_emulate () called w/o \
  1624. trap_type FPFLT or FPTRAP, OpCode = %8x%8x, and ISR code = %x\n",
  1625. (unsigned int)((OpCode >> 32) & 0xffffffff),
  1626. (unsigned int)(OpCode & 0xffffffff), ISRlow));
  1627. break;
  1628. case 18:
  1629. // err_nr = 18 in err1, bits 63-56
  1630. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: SWA fault repeated\n"));
  1631. break;
  1632. case 19:
  1633. // err_nr = 19 in err1, bits 63-56
  1634. // new_trap_type in err1, bits 31-0
  1635. new_trap_type = (unsigned int) (pal_ret.err1 & 0xffffffff);
  1636. HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: new_trap_type = %x\n",
  1637. new_trap_type));
  1638. break;
  1639. default:
  1640. // error
  1641. HalDebugPrint(( HAL_ERROR, "Incorrect err_nr = %8x%8x from fp_emulate ()\n",
  1642. (unsigned int)((err_nr >> 32) & 0xffffffff),
  1643. (unsigned int)(err_nr & 0xffffffff)));
  1644. }
  1645. }
  1646. LONG
  1647. HalFpEmulate (
  1648. ULONG trap_type,
  1649. BUNDLE *pbundle,
  1650. ULONGLONG *pipsr,
  1651. ULONGLONG *pfpsr,
  1652. ULONGLONG *pisr,
  1653. ULONGLONG *ppreds,
  1654. ULONGLONG *pifs,
  1655. FP_STATE *fp_state
  1656. )
  1657. /*++
  1658. Routine Description:
  1659. This function is a wrapper function to make fp_emulate() call
  1660. to EFI FPSWA driver.
  1661. Arguments:
  1662. trap_type - indicating which FP trap it is.
  1663. pbundle - bundle where this trap occurred
  1664. pipsr - IPSR value
  1665. pfpsr - FPSR value
  1666. pisr - ISR value
  1667. ppreds - value of predicate registers
  1668. pifs - IFS value
  1669. fp_state - floating point registers
  1670. Return Value:
  1671. return IEEE result of the floating point operation
  1672. --*/
  1673. {
  1674. PAL_RETURN ret;
  1675. ret = (*HalpFpEmulate) (
  1676. trap_type,
  1677. pbundle,
  1678. pipsr,
  1679. pfpsr,
  1680. pisr,
  1681. ppreds,
  1682. pifs,
  1683. fp_state
  1684. );
  1685. if (ret.retval == FP_EMUL_ERROR) {
  1686. HalpFpErrorPrint (ret);
  1687. }
  1688. return ((LONG) (ret.retval));
  1689. }