1 /** @file 2 3 Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php. 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 **/ 13 14 #include "SecFsp.h" 15 16 /** 17 18 Calculate the FSP IDT gate descriptor. 19 20 @param[in] IdtEntryTemplate IDT gate descriptor template. 21 22 @return FSP specific IDT gate descriptor. 23 24 **/ 25 UINT64 26 FspGetExceptionHandler( 27 IN UINT64 IdtEntryTemplate 28 ) 29 { 30 UINT32 Entry; 31 UINT64 ExceptionHandler; 32 IA32_IDT_GATE_DESCRIPTOR *IdtGateDescriptor; 33 FSP_INFO_HEADER *FspInfoHeader; 34 35 FspInfoHeader = (FSP_INFO_HEADER *)AsmGetFspInfoHeader(); 36 ExceptionHandler = IdtEntryTemplate; 37 IdtGateDescriptor = (IA32_IDT_GATE_DESCRIPTOR *)&ExceptionHandler; 38 Entry = (IdtGateDescriptor->Bits.OffsetHigh << 16) | IdtGateDescriptor->Bits.OffsetLow; 39 Entry = FspInfoHeader->ImageBase + FspInfoHeader->ImageSize - (~Entry + 1); 40 IdtGateDescriptor->Bits.OffsetHigh = (UINT16)(Entry >> 16); 41 IdtGateDescriptor->Bits.OffsetLow = (UINT16)Entry; 42 43 return ExceptionHandler; 44 } 45 46 /** 47 This interface fills platform specific data. 48 49 @param[in,out] FspData Pointer to the FSP global data. 50 51 **/ 52 VOID 53 EFIAPI 54 SecGetPlatformData ( 55 IN OUT FSP_GLOBAL_DATA *FspData 56 ) 57 { 58 FSP_PLAT_DATA *FspPlatformData; 59 UINT32 TopOfCar; 60 UINT32 *StackPtr; 61 UINT32 DwordSize; 62 63 FspPlatformData = &FspData->PlatformData; 64 65 // 66 // The entries of platform information, together with the number of them, 67 // reside in the bottom of stack, left untouched by normal stack operation. 68 // 69 70 FspPlatformData->DataPtr = NULL; 71 FspPlatformData->MicrocodeRegionBase = 0; 72 FspPlatformData->MicrocodeRegionSize = 0; 73 FspPlatformData->CodeRegionBase = 0; 74 FspPlatformData->CodeRegionSize = 0; 75 76 // 77 // Pointer to the size field 78 // 79 TopOfCar = PcdGet32(PcdTemporaryRamBase) + PcdGet32(PcdTemporaryRamSize); 80 StackPtr = (UINT32 *)(TopOfCar - sizeof (UINT32)); 81 82 if (*(StackPtr - 1) == FSP_MCUD_SIGNATURE) { 83 while (*StackPtr != 0) { 84 if (*(StackPtr - 1) == FSP_MCUD_SIGNATURE) { 85 // 86 // This following data was pushed onto stack after TempRamInit API 87 // 88 DwordSize = 4; 89 StackPtr = StackPtr - 1 - DwordSize; 90 CopyMem (&(FspPlatformData->MicrocodeRegionBase), StackPtr, (DwordSize << 2)); 91 StackPtr--; 92 } else if (*(StackPtr - 1) == FSP_PER0_SIGNATURE) { 93 // 94 // This is the performance data for InitTempMemory API entry/exit 95 // 96 DwordSize = 4; 97 StackPtr = StackPtr - 1 - DwordSize; 98 CopyMem (FspData->PerfData, StackPtr, (DwordSize << 2)); 99 100 ((UINT8 *)(&FspData->PerfData[0]))[7] = FSP_PERF_ID_API_TEMP_RAM_INIT_ENTRY; 101 ((UINT8 *)(&FspData->PerfData[1]))[7] = FSP_PERF_ID_API_TEMP_RAM_INIT_EXIT; 102 103 StackPtr--; 104 } else { 105 StackPtr -= (*StackPtr); 106 } 107 } 108 } 109 } 110 111 /** 112 113 Initialize the FSP global data region. 114 It needs to be done as soon as possible after the stack is setup. 115 116 @param[in,out] PeiFspData Pointer of the FSP global data. 117 @param[in] BootLoaderStack BootLoader stack. 118 @param[in] ApiIdx The index of the FSP API. 119 120 **/ 121 VOID 122 FspGlobalDataInit ( 123 IN OUT FSP_GLOBAL_DATA *PeiFspData, 124 IN UINT32 BootLoaderStack, 125 IN UINT8 ApiIdx 126 ) 127 { 128 VOID *FspmUpdDataPtr; 129 CHAR8 ImageId[9]; 130 UINTN Idx; 131 132 // 133 // Set FSP Global Data pointer 134 // 135 SetFspGlobalDataPointer (PeiFspData); 136 ZeroMem ((VOID *)PeiFspData, sizeof(FSP_GLOBAL_DATA)); 137 138 PeiFspData->Signature = FSP_GLOBAL_DATA_SIGNATURE; 139 PeiFspData->Version = 0; 140 PeiFspData->CoreStack = BootLoaderStack; 141 PeiFspData->PerfIdx = 2; 142 PeiFspData->PerfSig = FSP_PERFORMANCE_DATA_SIGNATURE; 143 144 SetFspMeasurePoint (FSP_PERF_ID_API_FSP_MEMORY_INIT_ENTRY); 145 146 // 147 // Get FSP Header offset 148 // It may have multiple FVs, so look into the last one for FSP header 149 // 150 PeiFspData->FspInfoHeader = (FSP_INFO_HEADER *)AsmGetFspInfoHeader(); 151 SecGetPlatformData (PeiFspData); 152 153 // 154 // Set API calling mode 155 // 156 SetFspApiCallingIndex (ApiIdx); 157 158 // 159 // Set UPD pointer 160 // 161 FspmUpdDataPtr = (VOID *) GetFspApiParameter (); 162 if (FspmUpdDataPtr == NULL) { 163 FspmUpdDataPtr = (VOID *)(PeiFspData->FspInfoHeader->ImageBase + PeiFspData->FspInfoHeader->CfgRegionOffset); 164 } 165 SetFspUpdDataPointer (FspmUpdDataPtr); 166 SetFspMemoryInitUpdDataPointer (FspmUpdDataPtr); 167 SetFspSiliconInitUpdDataPointer (NULL); 168 169 // 170 // Initialize serial port 171 // It might have been done in ProcessLibraryConstructorList(), however, 172 // the FSP global data is not initialized at that time. So do it again 173 // for safe. 174 // 175 SerialPortInitialize (); 176 177 // 178 // Ensure the golbal data pointer is valid 179 // 180 ASSERT (GetFspGlobalDataPointer () == PeiFspData); 181 182 for (Idx = 0; Idx < 8; Idx++) { 183 ImageId[Idx] = PeiFspData->FspInfoHeader->ImageId[Idx]; 184 } 185 ImageId[Idx] = 0; 186 187 DEBUG ((DEBUG_INFO | DEBUG_INIT, "\n============= FSP Spec v%d.%d Header Revision v%x (%a v%x.%x.%x.%x) =============\n", \ 188 (PeiFspData->FspInfoHeader->SpecVersion >> 4) & 0xF, \ 189 PeiFspData->FspInfoHeader->SpecVersion & 0xF, \ 190 PeiFspData->FspInfoHeader->HeaderRevision, \ 191 ImageId, \ 192 (PeiFspData->FspInfoHeader->ImageRevision >> 24) & 0xFF, \ 193 (PeiFspData->FspInfoHeader->ImageRevision >> 16) & 0xFF, \ 194 (PeiFspData->FspInfoHeader->ImageRevision >> 8) & 0xFF, \ 195 PeiFspData->FspInfoHeader->ImageRevision & 0xFF)); 196 } 197 198 /** 199 200 Adjust the FSP data pointers after the stack is migrated to memory. 201 202 @param[in] OffsetGap The offset gap between the old stack and the new stack. 203 204 **/ 205 VOID 206 FspDataPointerFixUp ( 207 IN UINT32 OffsetGap 208 ) 209 { 210 FSP_GLOBAL_DATA *NewFspData; 211 212 NewFspData = (FSP_GLOBAL_DATA *)((UINTN)GetFspGlobalDataPointer() + (UINTN)OffsetGap); 213 SetFspGlobalDataPointer (NewFspData); 214 } 215