EFIAPI AcquireSpinLock ( IN OUT SPIN_LOCK *SpinLock ) { UINT64 Current; UINT64 Previous; UINT64 Total; UINT64 Start; UINT64 End; UINT64 Timeout; INT64 Cycle; INT64 Delta; if (PcdGet32 (PcdSpinLockTimeout) > 0) { // // Get the current timer value // Current = GetPerformanceCounter(); // // Initialize local variables // Start = 0; End = 0; Total = 0; // // Retrieve the performance counter properties and compute the number of performance // counter ticks required to reach the timeout // Timeout = DivU64x32 ( MultU64x32 ( GetPerformanceCounterProperties (&Start, &End), PcdGet32 (PcdSpinLockTimeout) ), 1000000 ); Cycle = End - Start; if (Cycle < 0) { Cycle = -Cycle; } Cycle++; while (!AcquireSpinLockOrFail (SpinLock)) { CpuPause (); Previous = Current; Current = GetPerformanceCounter(); Delta = (INT64) (Current - Previous); if (Start > End) { Delta = -Delta; } if (Delta < 0) { Delta += Cycle; } Total += Delta; ASSERT (Total < Timeout); } } else { while (!AcquireSpinLockOrFail (SpinLock)) { CpuPause (); } } return SpinLock; }
/** Initialize the system (or sometimes called permanent) memory This memory is generally represented by the DRAM. This function is called from InitializeMemory() in MemoryInitPeim, in the PEI phase. **/ VOID ArmPlatformInitializeSystemMemory ( VOID ) { VOID *DeviceTreeBase; INT32 Node, Prev; UINT64 NewBase; UINT64 NewSize; CONST CHAR8 *Type; INT32 Len; CONST UINT64 *RegProp; NewBase = 0; NewSize = 0; DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress); ASSERT (DeviceTreeBase != NULL); // // Make sure we have a valid device tree blob // ASSERT (fdt_check_header (DeviceTreeBase) == 0); // // Look for a memory node // for (Prev = 0;; Prev = Node) { Node = fdt_next_node (DeviceTreeBase, Prev, NULL); if (Node < 0) { break; } // // Check for memory node // Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len); if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) { // // Get the 'reg' property of this node. For now, we will assume // two 8 byte quantities for base and size, respectively. // RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len); if (RegProp != 0 && Len == (2 * sizeof (UINT64))) { NewBase = fdt64_to_cpu (ReadUnaligned64 (RegProp)); NewSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1)); // // Make sure the start of DRAM matches our expectation // ASSERT (FixedPcdGet64 (PcdSystemMemoryBase) == NewBase); PcdSet64 (PcdSystemMemorySize, NewSize); DEBUG ((EFI_D_INFO, "%a: System RAM @ 0x%lx - 0x%lx\n", __FUNCTION__, NewBase, NewBase + NewSize - 1)); } else { DEBUG ((EFI_D_ERROR, "%a: Failed to parse FDT memory node\n", __FUNCTION__)); } break; } } // // We need to make sure that the machine we are running on has at least // 128 MB of memory configured, and is currently executing this binary from // NOR flash. This prevents a device tree image in DRAM from getting // clobbered when our caller installs permanent PEI RAM, before we have a // chance of marking its location as reserved or copy it to a freshly // allocated block in the permanent PEI RAM in the platform PEIM. // ASSERT (NewSize >= SIZE_128MB); ASSERT ( (((UINT64)PcdGet64 (PcdFdBaseAddress) + (UINT64)PcdGet32 (PcdFdSize)) <= NewBase) || ((UINT64)PcdGet64 (PcdFdBaseAddress) >= (NewBase + NewSize))); }
BOOLEAN ReadUsingMmio ( IN UINTN SpiOffset ) { return (BOOLEAN) ((SpiOffset >= BIOS_REGION_FLASH_OFFSET) && (SpiOffset < (BIOS_REGION_FLASH_OFFSET + PcdGet32 (PcdBiosImageSize))) && (!EfiAtRuntime ())); }
/** Initialize the state information for the CPU Architectural Protocol @param ImageHandle of the loaded driver @param SystemTable Pointer to the System Table @retval EFI_SUCCESS Protocol registered @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure @retval EFI_DEVICE_ERROR Hardware problems **/ EFI_STATUS InterruptDxeInitialize ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; UINTN Index; UINT32 RegOffset; UINTN RegShift; EFI_CPU_ARCH_PROTOCOL *Cpu; // Make sure the Interrupt Controller Protocol is not already installed in the system. ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid); mGicNumInterrupts = ArmGicGetMaxNumInterrupts (PcdGet32(PcdGicDistributorBase)); for (Index = 0; Index < mGicNumInterrupts; Index++) { DisableInterruptSource (&gHardwareInterruptProtocol, Index); // Set Priority RegOffset = Index / 4; RegShift = (Index % 4) * 8; MmioAndThenOr32 ( PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDIPR + (4*RegOffset), ~(0xff << RegShift), ARM_GIC_DEFAULT_PRIORITY << RegShift ); } // Configure interrupts for cpu 0 for (Index = 0; Index < (mGicNumInterrupts / 4); Index++) { MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDIPTR + (Index*4), 0x01010101); } // Set binary point reg to 0x7 (no preemption) MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCBPR, 0x7); // Set priority mask reg to 0xff to allow all priorities through MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCPMR, 0xff); // Enable gic cpu interface MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCICR, 0x1); // Enable gic distributor MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDDCR, 0x1); // Initialize the array for the Interrupt Handlers gRegisteredInterruptHandlers = (HARDWARE_INTERRUPT_HANDLER*)AllocateZeroPool (sizeof(HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts); Status = gBS->InstallMultipleProtocolInterfaces ( &gHardwareInterruptHandle, &gHardwareInterruptProtocolGuid, &gHardwareInterruptProtocol, NULL ); ASSERT_EFI_ERROR (Status); // // Get the CPU protocol that this driver requires. // Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu); ASSERT_EFI_ERROR(Status); // // Unregister the default exception handler. // Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, NULL); ASSERT_EFI_ERROR(Status); // // Register to receive interrupts // Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, IrqInterruptHandler); ASSERT_EFI_ERROR(Status); // Register for an ExitBootServicesEvent Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent); ASSERT_EFI_ERROR (Status); return Status; }
/** The user Entry Point for Application. The user code starts with this function as the real entry point for the image goes into a library that calls this function. @param[in] ImageHandle The firmware allocated handle for the EFI image. @param[in] SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The entry point is executed successfully. @retval other Some error occurs when executing this entry point. **/ EFI_STATUS EFIAPI InitializeUserInterface ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_HII_HANDLE HiiHandle; EFI_STATUS Status; EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut; UINTN BootTextColumn; UINTN BootTextRow; if (!mModeInitialized) { // // After the console is ready, get current video resolution // and text mode before launching setup at first time. // Status = gBS->HandleProtocol ( gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID**)&GraphicsOutput ); if (EFI_ERROR (Status)) { GraphicsOutput = NULL; } Status = gBS->HandleProtocol ( gST->ConsoleOutHandle, &gEfiSimpleTextOutProtocolGuid, (VOID**)&SimpleTextOut ); if (EFI_ERROR (Status)) { SimpleTextOut = NULL; } if (GraphicsOutput != NULL) { // // Get current video resolution and text mode. // mBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution; mBootVerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution; } if (SimpleTextOut != NULL) { Status = SimpleTextOut->QueryMode ( SimpleTextOut, SimpleTextOut->Mode->Mode, &BootTextColumn, &BootTextRow ); mBootTextModeColumn = (UINT32)BootTextColumn; mBootTextModeRow = (UINT32)BootTextRow; } // // Get user defined text mode for setup. // mSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution); mSetupVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution); mSetupTextModeColumn = PcdGet32 (PcdSetupConOutColumn); mSetupTextModeRow = PcdGet32 (PcdSetupConOutRow); mModeInitialized = TRUE; } gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL); gST->ConOut->ClearScreen (gST->ConOut); // // Install customized fonts needed by Front Page // HiiHandle = ExportFonts (); ASSERT (HiiHandle != NULL); InitializeStringSupport (); BdsSetConsoleMode (TRUE); UiEntry (FALSE); BdsSetConsoleMode (FALSE); UninitializeStringSupport (); HiiRemovePackages (HiiHandle); return EFI_SUCCESS; }
/** Initialize the state information for the CPU Architectural Protocol @param ImageHandle of the loaded driver @param SystemTable Pointer to the System Table @retval EFI_SUCCESS Protocol registered @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure @retval EFI_DEVICE_ERROR Hardware problems **/ EFI_STATUS GicV2DxeInitialize ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; UINTN Index; UINT32 RegOffset; UINTN RegShift; UINT32 CpuTarget; // Make sure the Interrupt Controller Protocol is not already installed in the system. ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid); mGicInterruptInterfaceBase = PcdGet32 (PcdGicInterruptInterfaceBase); mGicDistributorBase = PcdGet32 (PcdGicDistributorBase); mGicNumInterrupts = ArmGicGetMaxNumInterrupts (mGicDistributorBase); for (Index = 0; Index < mGicNumInterrupts; Index++) { GicV2DisableInterruptSource (&gHardwareInterruptV2Protocol, Index); // Set Priority RegOffset = Index / 4; RegShift = (Index % 4) * 8; MmioAndThenOr32 ( mGicDistributorBase + ARM_GIC_ICDIPR + (4 * RegOffset), ~(0xff << RegShift), ARM_GIC_DEFAULT_PRIORITY << RegShift ); } // // Targets the interrupts to the Primary Cpu // // Only Primary CPU will run this code. We can identify our GIC CPU ID by reading // the GIC Distributor Target register. The 8 first GICD_ITARGETSRn are banked to each // connected CPU. These 8 registers hold the CPU targets fields for interrupts 0-31. // More Info in the GIC Specification about "Interrupt Processor Targets Registers" // // Read the first Interrupt Processor Targets Register (that corresponds to the 4 // first SGIs) CpuTarget = MmioRead32 (mGicDistributorBase + ARM_GIC_ICDIPTR); // The CPU target is a bit field mapping each CPU to a GIC CPU Interface. This value // is 0 when we run on a uniprocessor platform. if (CpuTarget != 0) { // The 8 first Interrupt Processor Targets Registers are read-only for (Index = 8; Index < (mGicNumInterrupts / 4); Index++) { MmioWrite32 (mGicDistributorBase + ARM_GIC_ICDIPTR + (Index * 4), CpuTarget); } } // Set binary point reg to 0x7 (no preemption) MmioWrite32 (mGicInterruptInterfaceBase + ARM_GIC_ICCBPR, 0x7); // Set priority mask reg to 0xff to allow all priorities through MmioWrite32 (mGicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0xff); // Enable gic cpu interface ArmGicEnableInterruptInterface (mGicInterruptInterfaceBase); // Enable gic distributor ArmGicEnableDistributor (mGicDistributorBase); Status = InstallAndRegisterInterruptService ( &gHardwareInterruptV2Protocol, GicV2IrqInterruptHandler, GicV2ExitBootServicesEvent); return Status; }
/** Fault Tolerant Write protocol notification event handler. Non-Volatile variable write may needs FTW protocol to reclaim when writting variable. @param[in] Event Event whose notification function is being invoked. @param[in] Context Pointer to the notification function's context. **/ VOID EFIAPI FtwNotificationEvent ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_STATUS Status; EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol; EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol; EFI_PHYSICAL_ADDRESS NvStorageVariableBase; EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; EFI_PHYSICAL_ADDRESS BaseAddress; UINT64 Length; EFI_PHYSICAL_ADDRESS VariableStoreBase; UINT64 VariableStoreLength; // // Ensure FTW protocol is installed. // Status = GetFtwProtocol ((VOID**) &FtwProtocol); if (EFI_ERROR (Status)) { return ; } // // Find the proper FVB protocol for variable. // NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64); if (NvStorageVariableBase == 0) { NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase); } Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol); if (EFI_ERROR (Status)) { return ; } mVariableModuleGlobal->FvbInstance = FvbProtocol; // // Mark the variable storage region of the FLASH as RUNTIME. // VariableStoreBase = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase; VariableStoreLength = ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase)->Size; BaseAddress = VariableStoreBase & (~EFI_PAGE_MASK); Length = VariableStoreLength + (VariableStoreBase - BaseAddress); Length = (Length + EFI_PAGE_SIZE - 1) & (~EFI_PAGE_MASK); Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n")); } else { Status = gDS->SetMemorySpaceAttributes ( BaseAddress, Length, GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n")); } } Status = VariableWriteServiceInitialize (); ASSERT_EFI_ERROR (Status); // // Install the Variable Write Architectural protocol. // Status = gBS->InstallProtocolInterface ( &mHandle, &gEfiVariableWriteArchProtocolGuid, EFI_NATIVE_INTERFACE, NULL ); ASSERT_EFI_ERROR (Status); // // Close the notify event to avoid install gEfiVariableWriteArchProtocolGuid again. // gBS->CloseEvent (Event); }
/** This function will be called when MRC is done. @param PeiServices General purpose services available to every PEIM. @param NotifyDescriptor Information about the notify event.. @param Ppi The notify context. @retval EFI_SUCCESS If the function completed successfully. **/ EFI_STATUS EFIAPI MemoryDiscoveredPpiNotifyCallback ( IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi ) { EFI_STATUS Status; EFI_BOOT_MODE BootMode; UINT64 MemoryLength; EFI_SMRAM_DESCRIPTOR *SmramDescriptor; UINTN NumSmramRegions; UINT32 RmuMainBaseAddress; UINT32 RegData32; UINT8 CpuAddressWidth; UINT32 RegEax; MTRR_SETTINGS MtrrSettings; EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices; UINT8 MorControl; UINTN DataSize; DEBUG ((EFI_D_INFO, "Platform PEIM Memory Callback\n")); NumSmramRegions = 0; SmramDescriptor = NULL; RmuMainBaseAddress = 0; PERF_START (NULL, "SetCache", NULL, 0); InfoPostInstallMemory (&RmuMainBaseAddress, &SmramDescriptor, &NumSmramRegions); ASSERT (SmramDescriptor != NULL); ASSERT (RmuMainBaseAddress != 0); MemoryLength = ((UINT64) RmuMainBaseAddress) + 0x10000; Status = PeiServicesGetBootMode (&BootMode); ASSERT_EFI_ERROR (Status); // // Get current MTRR settings // MtrrGetAllMtrrs (&MtrrSettings); // // Set all DRAM cachability to CacheWriteBack // Status = MtrrSetMemoryAttributeInMtrrSettings (&MtrrSettings, 0, MemoryLength, CacheWriteBack); ASSERT_EFI_ERROR (Status); // // RTC:28208 - System hang/crash when entering probe mode(ITP) when relocating SMBASE // Workaround to make default SMRAM UnCachable // Status = MtrrSetMemoryAttributeInMtrrSettings (&MtrrSettings, 0x30000, SIZE_64KB, CacheUncacheable); ASSERT_EFI_ERROR (Status); // // Set new MTRR settings // MtrrSetAllMtrrs (&MtrrSettings); PERF_END (NULL, "SetCache", NULL, 0); // // Get necessary PPI // Status = PeiServicesLocatePpi ( &gEfiPeiReadOnlyVariable2PpiGuid, // GUID 0, // INSTANCE NULL, // EFI_PEI_PPI_DESCRIPTOR (VOID **)&VariableServices // PPI ); ASSERT_EFI_ERROR (Status); // // Detect MOR request by the OS. // MorControl = 0; DataSize = sizeof (MorControl); Status = VariableServices->GetVariable ( VariableServices, MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, &gEfiMemoryOverwriteControlDataGuid, NULL, &DataSize, &MorControl ); // // If OS requested a memory overwrite perform it now for Embedded SRAM // if (MOR_CLEAR_MEMORY_VALUE (MorControl)) { DEBUG ((EFI_D_INFO, "Clear Embedded SRAM per MOR request.\n")); if (PcdGet32 (PcdESramMemorySize) > 0) { if (PcdGet32 (PcdEsramStage1Base) == 0) { // // ZeroMem() generates an ASSERT() if Buffer parameter is NULL. // Clear byte at 0 and start clear operation at address 1. // *(UINT8 *)(0) = 0; ZeroMem ((VOID *)1, (UINTN)PcdGet32 (PcdESramMemorySize) - 1); } else { ZeroMem ( (VOID *)(UINTN)PcdGet32 (PcdEsramStage1Base), (UINTN)PcdGet32 (PcdESramMemorySize) ); } } } // // Install PeiReset for PeiResetSystem service // Status = PeiServicesInstallPpi (&mPpiList[0]); ASSERT_EFI_ERROR (Status); // // Do QNC initialization after MRC // PeiQNCPostMemInit (); Status = PeiServicesInstallPpi (&mPpiStall[0]); ASSERT_EFI_ERROR (Status); // // Set E000/F000 Routing // RegData32 = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC); RegData32 |= (BIT2|BIT1); QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, RegData32); if (BootMode == BOOT_IN_RECOVERY_MODE) { Status = PeimInitializeRecovery (PeiServices); ASSERT_EFI_ERROR (Status); } else if (BootMode == BOOT_ON_S3_RESUME) { return EFI_SUCCESS; } else { PeiServicesInstallFvInfoPpi ( NULL, (VOID *) (UINTN) PcdGet32 (PcdFlashFvMainBase), PcdGet32 (PcdFlashFvMainSize), NULL, NULL ); // // Publish the FVMAIN FV so the DXE Phase can dispatch drivers from this FV // and produce Load File Protocols for UEFI Applications in this FV. // BuildFvHob ( PcdGet32 (PcdFlashFvMainBase), PcdGet32 (PcdFlashFvMainSize) ); // // Publish the Payload FV so the DXE Phase can dispatch drivers from this FV // and produce Load File Protocols for UEFI Applications in this FV. // BuildFvHob ( PcdGet32 (PcdFlashFvPayloadBase), PcdGet32 (PcdFlashFvPayloadSize) ); } // // Build flash HOB, it's going to be used by GCD and E820 building // Map full SPI flash decode range (regardless of smaller SPI flash parts installed) // BuildResourceDescriptorHob ( EFI_RESOURCE_FIRMWARE_DEVICE, (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), (SIZE_4GB - SIZE_8MB), SIZE_8MB ); // // Create a CPU hand-off information // CpuAddressWidth = 32; AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL); if (RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) { AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &RegEax, NULL, NULL, NULL); CpuAddressWidth = (UINT8) (RegEax & 0xFF); } DEBUG ((EFI_D_INFO, "CpuAddressWidth: %d\n", CpuAddressWidth)); BuildCpuHob (CpuAddressWidth, 16); ASSERT_EFI_ERROR (Status); return Status; }
/** Initialises the FV Header and Variable Store Header to support variable operations. @param[in] Ptr - Location to initialise the headers **/ EFI_STATUS InitializeFvAndVariableStoreHeaders ( IN NOR_FLASH_INSTANCE *Instance ) { EFI_STATUS Status; VOID* Headers; UINTN HeadersLength; EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader; VARIABLE_STORE_HEADER *VariableStoreHeader; if (!Instance->Initialized && Instance->Initialize) { Instance->Initialize (Instance); } HeadersLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY) + sizeof(VARIABLE_STORE_HEADER); Headers = AllocateZeroPool(HeadersLength); // FirmwareVolumeHeader->FvLength is declared to have the Variable area AND the FTW working area AND the FTW Spare contiguous. ASSERT(PcdGet32(PcdFlashNvStorageVariableBase) + PcdGet32(PcdFlashNvStorageVariableSize) == PcdGet32(PcdFlashNvStorageFtwWorkingBase)); ASSERT(PcdGet32(PcdFlashNvStorageFtwWorkingBase) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) == PcdGet32(PcdFlashNvStorageFtwSpareBase)); // Check if the size of the area is at least one block size ASSERT((PcdGet32(PcdFlashNvStorageVariableSize) > 0) && (PcdGet32(PcdFlashNvStorageVariableSize) / Instance->Media.BlockSize > 0)); ASSERT((PcdGet32(PcdFlashNvStorageFtwWorkingSize) > 0) && (PcdGet32(PcdFlashNvStorageFtwWorkingSize) / Instance->Media.BlockSize > 0)); ASSERT((PcdGet32(PcdFlashNvStorageFtwSpareSize) > 0) && (PcdGet32(PcdFlashNvStorageFtwSpareSize) / Instance->Media.BlockSize > 0)); // Ensure the Variable area Base Addresses are aligned on a block size boundaries ASSERT(PcdGet32(PcdFlashNvStorageVariableBase) % Instance->Media.BlockSize == 0); ASSERT(PcdGet32(PcdFlashNvStorageFtwWorkingBase) % Instance->Media.BlockSize == 0); ASSERT(PcdGet32(PcdFlashNvStorageFtwSpareBase) % Instance->Media.BlockSize == 0); // // EFI_FIRMWARE_VOLUME_HEADER // FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Headers; CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid); FirmwareVolumeHeader->FvLength = PcdGet32(PcdFlashNvStorageVariableSize) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) + PcdGet32(PcdFlashNvStorageFtwSpareSize); FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE; FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2) ( EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled EFI_FVB2_READ_STATUS | // Reads are currently enabled EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY EFI_FVB2_MEMORY_MAPPED | // It is memory mapped EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1') EFI_FVB2_WRITE_STATUS | // Writes are currently enabled EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled ); FirmwareVolumeHeader->HeaderLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY); FirmwareVolumeHeader->Revision = EFI_FVH_REVISION; FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->Media.LastBlock + 1; FirmwareVolumeHeader->BlockMap[0].Length = Instance->Media.BlockSize; FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0; FirmwareVolumeHeader->BlockMap[1].Length = 0; FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ((UINT16*)FirmwareVolumeHeader,FirmwareVolumeHeader->HeaderLength); // // VARIABLE_STORE_HEADER // VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)Headers + FirmwareVolumeHeader->HeaderLength); CopyGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid); VariableStoreHeader->Size = PcdGet32(PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength; VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED; VariableStoreHeader->State = VARIABLE_STORE_HEALTHY; // Install the combined super-header in the NorFlash Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers); FreePool (Headers); return Status; }
/** Get the PCD entry pointer in PCD database. This routine will visit PCD database to find the PCD entry according to given token number. The given token number is autogened by build tools and it will be translated to local token number. Local token number contains PCD's type and offset of PCD entry in PCD database. @param TokenNumber Token's number, it is autogened by build tools @param GetSize The size of token's value @return PCD entry pointer in PCD database **/ VOID * GetWorker ( IN UINTN TokenNumber, IN UINTN GetSize ) { UINT32 Offset; EFI_GUID *Guid; UINT16 *Name; VARIABLE_HEAD *VariableHead; EFI_STATUS Status; UINTN DataSize; VOID *Data; UINT8 *StringTable; STRING_HEAD StringTableIdx; PEI_PCD_DATABASE *PeiPcdDb; UINT32 LocalTokenNumber; UINT32 LocalTokenCount; UINT8 *VaraiableDefaultBuffer; // // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER. // We have to decrement TokenNumber by 1 to make it usable // as the array index. // TokenNumber--; PeiPcdDb = GetPcdDatabase (); LocalTokenCount = PeiPcdDb->LocalTokenCount; // EBC compiler is very choosy. It may report warning about comparison // between UINTN and 0 . So we add 1 in each size of the // comparison. ASSERT (TokenNumber + 1 < (LocalTokenCount + 1)); ASSERT ((GetSize == PeiPcdGetSize(TokenNumber + 1)) || (GetSize == 0)); LocalTokenNumber = GetLocalTokenNumber (PeiPcdDb, TokenNumber + 1); Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK; StringTable = (UINT8 *)PeiPcdDb + PeiPcdDb->StringTableOffset; switch (LocalTokenNumber & PCD_TYPE_ALL_SET) { case PCD_TYPE_VPD: { VPD_HEAD *VpdHead; VpdHead = (VPD_HEAD *) ((UINT8 *)PeiPcdDb + Offset); return (VOID *) (UINTN) (PcdGet32 (PcdVpdBaseAddress) + VpdHead->Offset); } case PCD_TYPE_HII|PCD_TYPE_STRING: case PCD_TYPE_HII: { VariableHead = (VARIABLE_HEAD *) ((UINT8 *)PeiPcdDb + Offset); Guid = (EFI_GUID *) ((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset) + VariableHead->GuidTableIndex; Name = (UINT16*)&StringTable[VariableHead->StringIndex]; if ((LocalTokenNumber & PCD_TYPE_ALL_SET) == (PCD_TYPE_HII|PCD_TYPE_STRING)) { // // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of // string array in string table. // VaraiableDefaultBuffer = (UINT8 *) &StringTable[*(STRING_HEAD*)((UINT8*) PeiPcdDb + VariableHead->DefaultValueOffset)]; } else { VaraiableDefaultBuffer = (UINT8 *) PeiPcdDb + VariableHead->DefaultValueOffset; } Status = GetHiiVariable (Guid, Name, &Data, &DataSize); if ((Status == EFI_SUCCESS) && (DataSize >= (VariableHead->Offset + GetSize))) { if (GetSize == 0) { // // It is a pointer type. So get the MaxSize reserved for // this PCD entry. // GetPtrTypeSize (TokenNumber, &GetSize, PeiPcdDb); if (GetSize > (DataSize - VariableHead->Offset)) { // // Use actual valid size. // GetSize = DataSize - VariableHead->Offset; } } // // If the operation is successful, we copy the data // to the default value buffer in the PCD Database. // CopyMem (VaraiableDefaultBuffer, (UINT8 *) Data + VariableHead->Offset, GetSize); } return (VOID *) VaraiableDefaultBuffer; } case PCD_TYPE_DATA: return (VOID *) ((UINT8 *)PeiPcdDb + Offset); case PCD_TYPE_STRING: StringTableIdx = * (STRING_HEAD*) ((UINT8 *) PeiPcdDb + Offset); return (VOID *) (&StringTable[StringTableIdx]); default: ASSERT (FALSE); break; } ASSERT (FALSE); return NULL; }
EFI_STATUS EFIAPI MemoryDiscoveredPpiNotifyCallback ( IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi ) { EFI_STATUS Status; EFI_BOOT_MODE BootMode; UINT32 Pages; VOID* Memory; UINTN Size; // // Allocate LM memory and configure PDM if enabled by user. // ConfigureLM(PeiServices); // Status = (*PeiServices)->GetBootMode ( (const EFI_PEI_SERVICES **)PeiServices, &BootMode ); if (BootMode != BOOT_ON_S3_RESUME) { Size = (PcdGet32 (PcdFlashFvRecovery2Base) - PcdGet32 (PcdFlashFvMainBase)) + FixedPcdGet32(PcdFlashFvRecovery2Size); Pages= Size/0x1000; Memory = AllocatePages ( Pages ); CopyMem(Memory , (VOID *) FixedPcdGet32(PcdFlashFvMainBase) , Size); // // We don't verify just load // PeiServicesInstallFvInfoPpi ( NULL, (VOID *) ((UINTN) Memory + (PcdGet32 (PcdFlashFvRecovery2Base) - PcdGet32 (PcdFlashFvMainBase))), PcdGet32 (PcdFlashFvRecovery2Size), NULL, NULL ); PeiServicesInstallFvInfoPpi ( NULL, (VOID *) Memory, PcdGet32 (PcdFlashFvMainSize), NULL, NULL ); } if (BootMode == BOOT_ON_S3_RESUME) { PeiServicesInstallFvInfoPpi ( NULL, (VOID *) (UINTN) (PcdGet32 (PcdFlashFvRecovery2Base)), PcdGet32 (PcdFlashFvRecovery2Size), NULL, NULL ); } return EFI_SUCCESS; }
/** The function registers the CallBackOnSet fucntion according to TokenNumber and EFI_GUID space. @param ExTokenNumber The token number. @param Guid The GUID space. @param CallBackFunction The Callback function to be registered. @param Register To register or unregister the callback function. @retval EFI_SUCCESS If the Callback function is registered. @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space. @retval EFI_OUT_OF_RESOURCES If the callback function can't be registered because there is not free slot left in the CallbackFnTable. @retval EFI_INVALID_PARAMETER If the callback function want to be de-registered can not be found. **/ EFI_STATUS PeiRegisterCallBackWorker ( IN UINTN ExTokenNumber, IN CONST EFI_GUID *Guid, OPTIONAL IN PCD_PPI_CALLBACK CallBackFunction, IN BOOLEAN Register ) { EFI_HOB_GUID_TYPE *GuidHob; PCD_PPI_CALLBACK *CallbackTable; PCD_PPI_CALLBACK Compare; PCD_PPI_CALLBACK Assign; UINT32 LocalTokenNumber; UINT32 LocalTokenCount; UINTN PeiNexTokenNumber; UINTN TokenNumber; UINTN Idx; PEI_PCD_DATABASE *PeiPcdDb; PeiPcdDb = GetPcdDatabase(); LocalTokenCount = PeiPcdDb->LocalTokenCount; PeiNexTokenNumber = PeiPcdDb->LocalTokenCount - PeiPcdDb->ExTokenCount; if (Guid == NULL) { TokenNumber = ExTokenNumber; // // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER. // We have to decrement TokenNumber by 1 to make it usable // as the array index. // TokenNumber--; ASSERT (TokenNumber + 1 < (PeiNexTokenNumber + 1)); } else { TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber); if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) { return EFI_NOT_FOUND; } // // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER. // We have to decrement TokenNumber by 1 to make it usable // as the array index. // TokenNumber--; // EBC compiler is very choosy. It may report warning about comparison // between UINTN and 0 . So we add 1 in each size of the // comparison. ASSERT ((TokenNumber + 1) < (LocalTokenCount + 1)); } LocalTokenNumber = *((UINT32 *)((UINT8 *)PeiPcdDb + PeiPcdDb->LocalTokenNumberTableOffset) + TokenNumber); // // We don't support SET for HII and VPD type PCD entry in PEI phase. // So we will assert if any register callback for such PCD entry. // ASSERT ((LocalTokenNumber & PCD_TYPE_HII) == 0); ASSERT ((LocalTokenNumber & PCD_TYPE_VPD) == 0); GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid); ASSERT (GuidHob != NULL); CallbackTable = GET_GUID_HOB_DATA (GuidHob); CallbackTable = CallbackTable + (TokenNumber * PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry)); Compare = Register? NULL: CallBackFunction; Assign = Register? CallBackFunction: NULL; for (Idx = 0; Idx < PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) { if (CallbackTable[Idx] == Compare) { CallbackTable[Idx] = Assign; return EFI_SUCCESS; } } return Register? EFI_OUT_OF_RESOURCES : EFI_INVALID_PARAMETER; }
/** Function to Copy one file to another location If the destination exists the user will be prompted and the result put into *resp @param[in] Source pointer to source file name @param[in] Dest pointer to destination file name @param[out] Resp pointer to response from question. Pass back on looped calling @param[in] SilentMode whether to run in quiet mode or not @param[in] CmdName Source command name requesting single file copy @retval SHELL_SUCCESS The source file was copied to the destination **/ SHELL_STATUS CopySingleFile( IN CONST CHAR16 *Source, IN CONST CHAR16 *Dest, OUT VOID **Resp, IN BOOLEAN SilentMode, IN CONST CHAR16 *CmdName ) { VOID *Response; UINTN ReadSize; SHELL_FILE_HANDLE SourceHandle; SHELL_FILE_HANDLE DestHandle; EFI_STATUS Status; VOID *Buffer; CHAR16 *TempName; UINTN Size; EFI_SHELL_FILE_INFO *List; SHELL_STATUS ShellStatus; UINT64 SourceFileSize; UINT64 DestFileSize; EFI_FILE_PROTOCOL *DestVolumeFP; EFI_FILE_SYSTEM_INFO *DestVolumeInfo; UINTN DestVolumeInfoSize; ASSERT(Resp != NULL); SourceHandle = NULL; DestHandle = NULL; Response = *Resp; List = NULL; DestVolumeInfo = NULL; ShellStatus = SHELL_SUCCESS; ReadSize = PcdGet32(PcdShellFileOperationSize); // Why bother copying a file to itself if (StrCmp(Source, Dest) == 0) { return (SHELL_SUCCESS); } // // if the destination file existed check response and possibly prompt user // if (ShellFileExists(Dest) == EFI_SUCCESS) { if (Response == NULL && !SilentMode) { Status = ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR), gShellLevel2HiiHandle, &Response); } // // possibly return based on response // if (!SilentMode) { switch (*(SHELL_PROMPT_RESPONSE*)Response) { case ShellPromptResponseNo: // // return success here so we dont stop the process // return (SHELL_SUCCESS); case ShellPromptResponseCancel: *Resp = Response; // // indicate to stop everything // return (SHELL_ABORTED); case ShellPromptResponseAll: *Resp = Response; case ShellPromptResponseYes: break; default: return SHELL_ABORTED; } } } if (ShellIsDirectory(Source) == EFI_SUCCESS) { Status = ShellCreateDirectory(Dest, &DestHandle); if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_DIR_FAIL), gShellLevel2HiiHandle, CmdName, Dest); return (SHELL_ACCESS_DENIED); } // // Now copy all the files under the directory... // TempName = NULL; Size = 0; StrnCatGrow(&TempName, &Size, Source, 0); StrnCatGrow(&TempName, &Size, L"\\*", 0); if (TempName != NULL) { ShellOpenFileMetaArg((CHAR16*)TempName, EFI_FILE_MODE_READ, &List); *TempName = CHAR_NULL; StrnCatGrow(&TempName, &Size, Dest, 0); StrnCatGrow(&TempName, &Size, L"\\", 0); ShellStatus = ValidateAndCopyFiles(List, TempName, SilentMode, TRUE, Resp); ShellCloseFileMetaArg(&List); SHELL_FREE_NON_NULL(TempName); Size = 0; } } else { Status = ShellDeleteFileByName(Dest); // // open file with create enabled // Status = ShellOpenFileByName(Dest, &DestHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_OPEN_FAIL), gShellLevel2HiiHandle, CmdName, Dest); return (SHELL_ACCESS_DENIED); } // // open source file // Status = ShellOpenFileByName (Source, &SourceHandle, EFI_FILE_MODE_READ, 0); if (EFI_ERROR (Status)) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CP_SRC_OPEN_FAIL), gShellLevel2HiiHandle, CmdName, Source); return (SHELL_ACCESS_DENIED); } // //get file size of source file and freespace available on destination volume // ShellGetFileSize(SourceHandle, &SourceFileSize); ShellGetFileSize(DestHandle, &DestFileSize); // //if the destination file already exists then it will be replaced, meaning the sourcefile effectively needs less storage space // if(DestFileSize < SourceFileSize){ SourceFileSize -= DestFileSize; } else { SourceFileSize = 0; } // //get the system volume info to check the free space // DestVolumeFP = ConvertShellHandleToEfiFileProtocol(DestHandle); DestVolumeInfo = NULL; DestVolumeInfoSize = 0; Status = DestVolumeFP->GetInfo( DestVolumeFP, &gEfiFileSystemInfoGuid, &DestVolumeInfoSize, DestVolumeInfo ); if (Status == EFI_BUFFER_TOO_SMALL) { DestVolumeInfo = AllocateZeroPool(DestVolumeInfoSize); Status = DestVolumeFP->GetInfo( DestVolumeFP, &gEfiFileSystemInfoGuid, &DestVolumeInfoSize, DestVolumeInfo ); } // //check if enough space available on destination drive to complete copy // if (DestVolumeInfo!= NULL && (DestVolumeInfo->FreeSpace < SourceFileSize)) { // //not enough space on destination directory to copy file // SHELL_FREE_NON_NULL(DestVolumeInfo); ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_FAIL), gShellLevel2HiiHandle, CmdName); return(SHELL_VOLUME_FULL); } else { // // copy data between files // Buffer = AllocateZeroPool(ReadSize); if (Buffer == NULL) { ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, CmdName); return SHELL_OUT_OF_RESOURCES; } while (ReadSize == PcdGet32(PcdShellFileOperationSize) && !EFI_ERROR(Status)) { Status = ShellReadFile(SourceHandle, &ReadSize, Buffer); if (!EFI_ERROR(Status)) { Status = ShellWriteFile(DestHandle, &ReadSize, Buffer); if (EFI_ERROR(Status)) { ShellStatus = (SHELL_STATUS) (Status & (~MAX_BIT)); ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_WRITE_ERROR), gShellLevel2HiiHandle, CmdName, Dest); break; } } else { ShellStatus = (SHELL_STATUS) (Status & (~MAX_BIT)); ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_READ_ERROR), gShellLevel2HiiHandle, CmdName, Source); break; } } } SHELL_FREE_NON_NULL(DestVolumeInfo); } // // close files // if (DestHandle != NULL) { ShellCloseFile(&DestHandle); DestHandle = NULL; } if (SourceHandle != NULL) { ShellCloseFile(&SourceHandle); SourceHandle = NULL; } // // return // return ShellStatus; }
/** The module Entry Point of the Firmware Performance Data Table DXE driver. @param[in] ImageHandle The firmware allocated handle for the EFI image. @param[in] SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The entry point is executed successfully. @retval Other Some error occurs when executing this entry point. **/ EFI_STATUS EFIAPI FirmwarePerformanceDxeEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_HOB_GUID_TYPE *GuidHob; FIRMWARE_SEC_PERFORMANCE *Performance; VOID *Registration; UINT64 OemTableId; CopyMem ( mFirmwarePerformanceTableTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mFirmwarePerformanceTableTemplate.Header.OemId) ); OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId); CopyMem (&mFirmwarePerformanceTableTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64)); mFirmwarePerformanceTableTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision); mFirmwarePerformanceTableTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId); mFirmwarePerformanceTableTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision); // // Get Report Status Code Handler Protocol. // Status = gBS->LocateProtocol (&gEfiRscHandlerProtocolGuid, NULL, (VOID **) &mRscHandlerProtocol); ASSERT_EFI_ERROR (Status); // // Register report status code listener for OS Loader load and start. // Status = mRscHandlerProtocol->Register (FpdtStatusCodeListenerDxe, TPL_HIGH_LEVEL); ASSERT_EFI_ERROR (Status); // // Register the notify function to update FPDT on ExitBootServices Event. // Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, FpdtExitBootServicesEventNotify, NULL, &gEfiEventExitBootServicesGuid, &mExitBootServicesEvent ); ASSERT_EFI_ERROR (Status); // // Create ready to boot event to install ACPI FPDT table. // Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, FpdtReadyToBootEventNotify, NULL, &gEfiEventReadyToBootGuid, &mReadyToBootEvent ); ASSERT_EFI_ERROR (Status); // // Retrieve GUID HOB data that contains the ResetEnd. // GuidHob = GetFirstGuidHob (&gEfiFirmwarePerformanceGuid); if (GuidHob != NULL) { Performance = (FIRMWARE_SEC_PERFORMANCE *) GET_GUID_HOB_DATA (GuidHob); mBootPerformanceTableTemplate.BasicBoot.ResetEnd = Performance->ResetEnd; } else { // // SEC Performance Data Hob not found, ResetEnd in ACPI FPDT table will be 0. // DEBUG ((EFI_D_ERROR, "FPDT: WARNING: SEC Performance Data Hob not found, ResetEnd will be set to 0!\n")); } if (FeaturePcdGet (PcdFirmwarePerformanceDataTableS3Support)) { // // Register callback function upon VariableArchProtocol and LockBoxProtocol // to allocate S3 performance table memory and save the pointer to LockBox. // EfiCreateProtocolNotifyEvent ( &gEfiVariableArchProtocolGuid, TPL_CALLBACK, FpdtAllocateS3PerformanceTableMemory, NULL, &Registration ); EfiCreateProtocolNotifyEvent ( &gEfiLockBoxProtocolGuid, TPL_CALLBACK, FpdtAllocateS3PerformanceTableMemory, NULL, &Registration ); } else { // // Exclude S3 Performance Table Pointer from FPDT table template. // mFirmwarePerformanceTableTemplate.Header.Length -= sizeof (EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD); } return EFI_SUCCESS; }
EFI_STATUS EFIAPI PeimInitializeWinNtFwh ( IN EFI_FFS_FILE_HEADER *FfsHeader, IN EFI_PEI_SERVICES **PeiServices ) /*++ Routine Description: Perform a call-back into the SEC simulator to get address of the Firmware Hub Arguments: FfsHeader - Ffs Header available to every PEIM PeiServices - General purpose services available to every PEIM. Returns: None --*/ { EFI_STATUS Status; EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; NT_FWH_PPI *FwhPpi; EFI_PHYSICAL_ADDRESS FdBase; EFI_FIRMWARE_VOLUME_HEADER *FvHeader; UINT64 FdSize; UINTN Index; DEBUG ((EFI_D_ERROR, "NT 32 Firmware Volume PEIM Loaded\n")); // // Get the Fwh Information PPI // Status = (**PeiServices).LocatePpi ( (const EFI_PEI_SERVICES **)PeiServices, &gNtFwhPpiGuid, // GUID 0, // INSTANCE &PpiDescriptor, // EFI_PEI_PPI_DESCRIPTOR (VOID**)&FwhPpi // PPI ); ASSERT_EFI_ERROR (Status); Index = 0; do { // // Get information about all the FD's in the system // Status = FwhPpi->NtFwh (Index, &FdBase, &FdSize); if (!EFI_ERROR (Status)) { // // Assume the FD starts with an FV header // FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FdBase; // // Make an FV Hob for the first FV in the FD // BuildFvHob (FdBase, FvHeader->FvLength); if (Index == 0) { // // Assume the first FD was produced by the NT32.DSC // All these strange offests are needed to keep in // sync with the FlashMap and NT32.dsc file // BuildResourceDescriptorHob ( EFI_RESOURCE_FIRMWARE_DEVICE, (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), FdBase, ( FvHeader->FvLength + PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + PcdGet32 (PcdFlashNvStorageFtwSpareSize) + PcdGet32 (PcdWinNtFlashNvStorageEventLogSize) ) ); // // Hard code the address of the spare block and variable services. // Assume it's a hard coded offset from FV0 in FD0. // FdSize = PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + PcdGet32 (PcdFlashNvStorageFtwSpareSize) + PcdGet32 (PcdWinNtFlashNvStorageEventLogSize); BuildFvHob (FdBase + PcdGet32 (PcdWinNtFlashNvStorageVariableBase), FdSize); } else { // // For other FD's just map them in. // BuildResourceDescriptorHob ( EFI_RESOURCE_FIRMWARE_DEVICE, (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), FdBase, FdSize ); } } Index++; } while (!EFI_ERROR (Status)); return Status; }
/** Publish TPM2 ACPI table @retval EFI_SUCCESS The TPM2 ACPI table is published successfully. @retval Others The TPM2 ACPI table is not published. **/ EFI_STATUS PublishTpm2 ( VOID ) { EFI_STATUS Status; EFI_ACPI_TABLE_PROTOCOL *AcpiTable; UINTN TableKey; UINT64 OemTableId; EFI_TPM2_ACPI_CONTROL_AREA *ControlArea; PTP_INTERFACE_TYPE InterfaceType; // // Measure to PCR[0] with event EV_POST_CODE ACPI DATA // TpmMeasureAndLogData( 0, EV_POST_CODE, EV_POSTCODE_INFO_ACPI_DATA, ACPI_DATA_LEN, &mTpm2AcpiTemplate, sizeof(mTpm2AcpiTemplate) ); InterfaceType = GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress)); switch (InterfaceType) { case PtpInterfaceCrb: mTpm2AcpiTemplate.StartMethod = EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE; mTpm2AcpiTemplate.AddressOfControlArea = PcdGet64 (PcdTpmBaseAddress) + 0x40; ControlArea = (EFI_TPM2_ACPI_CONTROL_AREA *)(UINTN)mTpm2AcpiTemplate.AddressOfControlArea; ControlArea->CommandSize = 0xF80; ControlArea->ResponseSize = 0xF80; ControlArea->Command = PcdGet64 (PcdTpmBaseAddress) + 0x80; ControlArea->Response = PcdGet64 (PcdTpmBaseAddress) + 0x80; break; case PtpInterfaceFifo: case PtpInterfaceTis: break; default: DEBUG((EFI_D_ERROR, "TPM2 InterfaceType get error! %d\n", InterfaceType)); break; } CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId)); OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId); CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64)); mTpm2AcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision); mTpm2AcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId); mTpm2AcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision); // // Construct ACPI table // Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable); ASSERT_EFI_ERROR (Status); Status = AcpiTable->InstallAcpiTable ( AcpiTable, &mTpm2AcpiTemplate, sizeof(mTpm2AcpiTemplate), &TableKey ); ASSERT_EFI_ERROR (Status); return Status; }
VOID MemMapInitialization ( VOID ) { // // Create Memory Type Information HOB // BuildGuidDataHob ( &gEfiMemoryTypeInformationGuid, mDefaultMemoryTypeInformation, sizeof(mDefaultMemoryTypeInformation) ); // // Add PCI IO Port space available for PCI resource allocations. // BuildResourceDescriptorHob ( EFI_RESOURCE_IO, EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED, PcdGet64 (PcdPciIoBase), PcdGet64 (PcdPciIoSize) ); // // Video memory + Legacy BIOS region // AddIoMemoryRangeHob (0x0A0000, BASE_1MB); if (!mXen) { UINT32 TopOfLowRam; UINT64 PciExBarBase; UINT32 PciBase; UINT32 PciSize; TopOfLowRam = GetSystemMemorySizeBelow4gb (); PciExBarBase = 0; if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) { // // The MMCONFIG area is expected to fall between the top of low RAM and // the base of the 32-bit PCI host aperture. // PciExBarBase = FixedPcdGet64 (PcdPciExpressBaseAddress); ASSERT (TopOfLowRam <= PciExBarBase); ASSERT (PciExBarBase <= MAX_UINT32 - SIZE_256MB); PciBase = (UINT32)(PciExBarBase + SIZE_256MB); } else { PciBase = (TopOfLowRam < BASE_2GB) ? BASE_2GB : TopOfLowRam; } // // address purpose size // ------------ -------- ------------------------- // max(top, 2g) PCI MMIO 0xFC000000 - max(top, 2g) // 0xFC000000 gap 44 MB // 0xFEC00000 IO-APIC 4 KB // 0xFEC01000 gap 1020 KB // 0xFED00000 HPET 1 KB // 0xFED00400 gap 111 KB // 0xFED1C000 gap (PIIX4) / RCRB (ICH9) 16 KB // 0xFED20000 gap 896 KB // 0xFEE00000 LAPIC 1 MB // PciSize = 0xFC000000 - PciBase; AddIoMemoryBaseSizeHob (PciBase, PciSize); PcdSet64 (PcdPciMmio32Base, PciBase); PcdSet64 (PcdPciMmio32Size, PciSize); AddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB); AddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB); if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) { AddIoMemoryBaseSizeHob (ICH9_ROOT_COMPLEX_BASE, SIZE_16KB); // // Note: there should be an // // AddIoMemoryBaseSizeHob (PciExBarBase, SIZE_256MB); // // call below, just like the one above for RCBA. However, Linux insists // that the MMCONFIG area be marked in the E820 or UEFI memory map as // "reserved memory" -- Linux does not content itself with a simple gap // in the memory map wherever the MCFG ACPI table points to. // // This appears to be a safety measure. The PCI Firmware Specification // (rev 3.1) says in 4.1.2. "MCFG Table Description": "The resources can // *optionally* be returned in [...] EFIGetMemoryMap as reserved memory // [...]". (Emphasis added here.) // // Normally we add memory resource descriptor HOBs in // QemuInitializeRam(), and pre-allocate from those with memory // allocation HOBs in InitializeRamRegions(). However, the MMCONFIG area // is most definitely not RAM; so, as an exception, cover it with // uncacheable reserved memory right here. // AddReservedMemoryBaseSizeHob (PciExBarBase, SIZE_256MB, FALSE); BuildMemoryAllocationHob (PciExBarBase, SIZE_256MB, EfiReservedMemoryType); } AddIoMemoryBaseSizeHob (PcdGet32(PcdCpuLocalApicBaseAddress), SIZE_1MB); } }
/** The module Entry Point of the CPU SMM driver. @param ImageHandle The firmware allocated handle for the EFI image. @param SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The entry point is executed successfully. @retval Other Some error occurs when executing this entry point. **/ EFI_STATUS EFIAPI PiCpuSmmEntry ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_MP_SERVICES_PROTOCOL *MpServices; UINTN NumberOfEnabledProcessors; UINTN Index; VOID *Buffer; UINTN BufferPages; UINTN TileCodeSize; UINTN TileDataSize; UINTN TileSize; UINT8 *Stacks; VOID *Registration; UINT32 RegEax; UINT32 RegEdx; UINTN FamilyId; UINTN ModelId; UINT32 Cr3; // // Initialize Debug Agent to support source level debug in SMM code // InitializeDebugAgent (DEBUG_AGENT_INIT_SMM, NULL, NULL); // // Report the start of CPU SMM initialization. // REPORT_STATUS_CODE ( EFI_PROGRESS_CODE, EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_SMM_INIT ); // // Fix segment address of the long-mode-switch jump // if (sizeof (UINTN) == sizeof (UINT64)) { gSmmJmpAddr.Segment = LONG_MODE_CODE_SEGMENT; } // // Find out SMRR Base and SMRR Size // FindSmramInfo (&mCpuHotPlugData.SmrrBase, &mCpuHotPlugData.SmrrSize); // // Get MP Services Protocol // Status = SystemTable->BootServices->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpServices); ASSERT_EFI_ERROR (Status); // // Use MP Services Protocol to retrieve the number of processors and number of enabled processors // Status = MpServices->GetNumberOfProcessors (MpServices, &mNumberOfCpus, &NumberOfEnabledProcessors); ASSERT_EFI_ERROR (Status); ASSERT (mNumberOfCpus <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber)); // // If support CPU hot plug, PcdCpuSmmEnableBspElection should be set to TRUE. // A constant BSP index makes no sense because it may be hot removed. // DEBUG_CODE ( if (FeaturePcdGet (PcdCpuHotPlugSupport)) { ASSERT (FeaturePcdGet (PcdCpuSmmEnableBspElection)); } );
/** Perform USB erratas after MRC init. **/ VOID PlatformUsbErratasPostMrc ( VOID ) { UINT32 Index; UINT32 TempBar0Addr; UINT16 SaveCmdReg; UINT32 SaveBar0Reg; TempBar0Addr = PcdGet32(PcdPeiQNCUsbControllerMemoryBaseAddress); // // Apply EHCI controller erratas. // for (Index = 0; Index < IOH_MAX_EHCI_USB_CONTROLLERS; Index++, TempBar0Addr += IOH_USB_CONTROLLER_MMIO_RANGE) { if ((PciRead16 (IohEhciPciReg[Index] + R_IOH_USB_VENDOR_ID)) != V_IOH_USB_VENDOR_ID) { continue; // Device not enabled, skip. } // // Save current settings for PCI CMD/BAR0 registers // SaveCmdReg = PciRead16 (IohEhciPciReg[Index] + R_IOH_USB_COMMAND); SaveBar0Reg = PciRead32 (IohEhciPciReg[Index] + R_IOH_USB_MEMBAR); // // Temp. assign base address register, Enable Memory Space. // PciWrite32 ((IohEhciPciReg[Index] + R_IOH_USB_MEMBAR), TempBar0Addr); PciWrite16 (IohEhciPciReg[Index] + R_IOH_USB_COMMAND, SaveCmdReg | B_IOH_USB_COMMAND_MSE); // // Set packet buffer OUT/IN thresholds. // MmioAndThenOr32 ( TempBar0Addr + R_IOH_EHCI_INSNREG01, (UINT32) (~(B_IOH_EHCI_INSNREG01_OUT_THRESHOLD_MASK | B_IOH_EHCI_INSNREG01_IN_THRESHOLD_MASK)), (UINT32) ((EHCI_OUT_THRESHOLD_VALUE << B_IOH_EHCI_INSNREG01_OUT_THRESHOLD_BP) | (EHCI_IN_THRESHOLD_VALUE << B_IOH_EHCI_INSNREG01_IN_THRESHOLD_BP)) ); // // Restore settings for PCI CMD/BAR0 registers // PciWrite32 ((IohEhciPciReg[Index] + R_IOH_USB_MEMBAR), SaveBar0Reg); PciWrite16 (IohEhciPciReg[Index] + R_IOH_USB_COMMAND, SaveCmdReg); } // // Apply USB device controller erratas. // for (Index = 0; Index < IOH_MAX_USBDEVICE_USB_CONTROLLERS; Index++, TempBar0Addr += IOH_USB_CONTROLLER_MMIO_RANGE) { if ((PciRead16 (IohUsbDevicePciReg[Index] + R_IOH_USB_VENDOR_ID)) != V_IOH_USB_VENDOR_ID) { continue; // Device not enabled, skip. } // // Save current settings for PCI CMD/BAR0 registers // SaveCmdReg = PciRead16 (IohUsbDevicePciReg[Index] + R_IOH_USB_COMMAND); SaveBar0Reg = PciRead32 (IohUsbDevicePciReg[Index] + R_IOH_USB_MEMBAR); // // Temp. assign base address register, Enable Memory Space. // PciWrite32 ((IohUsbDevicePciReg[Index] + R_IOH_USB_MEMBAR), TempBar0Addr); PciWrite16 (IohUsbDevicePciReg[Index] + R_IOH_USB_COMMAND, SaveCmdReg | B_IOH_USB_COMMAND_MSE); // // Erratas for USB Device interrupt registers. // // // 1st Mask interrupts. // MmioWrite32 ( TempBar0Addr + R_IOH_USBDEVICE_D_INTR_MSK_UDC_REG, V_IOH_USBDEVICE_D_INTR_MSK_UDC_REG ); // // 2nd RW/1C of equivalent status bits. // MmioWrite32 ( TempBar0Addr + R_IOH_USBDEVICE_D_INTR_UDC_REG, V_IOH_USBDEVICE_D_INTR_MSK_UDC_REG ); // // 1st Mask end point interrupts. // MmioWrite32 ( TempBar0Addr + R_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG, V_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG ); // // 2nd RW/1C of equivalent end point status bits. // MmioWrite32 ( TempBar0Addr + R_IOH_USBDEVICE_EP_INTR_UDC_REG, V_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG ); // // Restore settings for PCI CMD/BAR0 registers // PciWrite32 ((IohUsbDevicePciReg[Index] + R_IOH_USB_MEMBAR), SaveBar0Reg); PciWrite16 (IohUsbDevicePciReg[Index] + R_IOH_USB_COMMAND, SaveCmdReg); } }
/*++ Routine Description: Arguments: FileHandle - Handle of the file being invoked. PeiServices - Describes the list of possible PEI Services. Returns: Status - EFI_SUCCESS if the boot mode could be set --*/ EFI_STATUS EFIAPI MemoryPeim ( IN EFI_PHYSICAL_ADDRESS UefiMemoryBase, IN UINT64 UefiMemorySize ) { EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttributes; UINT64 ResourceLength; EFI_PEI_HOB_POINTERS NextHob; EFI_PHYSICAL_ADDRESS FdTop; EFI_PHYSICAL_ADDRESS SystemMemoryTop; EFI_PHYSICAL_ADDRESS ResourceTop; BOOLEAN Found; // Ensure PcdSystemMemorySize has been set ASSERT (PcdGet32 (PcdSystemMemorySize) != 0); // // Now, the permanent memory has been installed, we can call AllocatePages() // ResourceAttributes = ( EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | EFI_RESOURCE_ATTRIBUTE_TESTED ); // Reserved the memory space occupied by the firmware volume BuildResourceDescriptorHob ( EFI_RESOURCE_SYSTEM_MEMORY, ResourceAttributes, PcdGet32 (PcdSystemMemoryBase), PcdGet32 (PcdSystemMemorySize) ); SystemMemoryTop = PcdGet32 (PcdSystemMemoryBase) + PcdGet32 (PcdSystemMemorySize); FdTop = PcdGet32(PcdFdBaseAddress) + PcdGet32(PcdFdSize); // EDK2 does not have the concept of boot firmware copied into DRAM. To avoid the DXE // core to overwrite this area we must mark the region with the attribute non-present if ((PcdGet32 (PcdFdBaseAddress) >= PcdGet32 (PcdSystemMemoryBase)) && (FdTop <= SystemMemoryTop)) { Found = FALSE; // Search for System Memory Hob that contains the firmware NextHob.Raw = GetHobList (); while ((NextHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, NextHob.Raw)) != NULL) { if ((NextHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) && (PcdGet32(PcdFdBaseAddress) >= NextHob.ResourceDescriptor->PhysicalStart) && (FdTop <= NextHob.ResourceDescriptor->PhysicalStart + NextHob.ResourceDescriptor->ResourceLength)) { ResourceAttributes = NextHob.ResourceDescriptor->ResourceAttribute; ResourceLength = NextHob.ResourceDescriptor->ResourceLength; ResourceTop = NextHob.ResourceDescriptor->PhysicalStart + ResourceLength; if (PcdGet32(PcdFdBaseAddress) == NextHob.ResourceDescriptor->PhysicalStart) { if (SystemMemoryTop == FdTop) { NextHob.ResourceDescriptor->ResourceAttribute = ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT; } else { // Create the System Memory HOB for the firmware with the non-present attribute BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY, ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT, PcdGet32(PcdFdBaseAddress), PcdGet32(PcdFdSize)); // Top of the FD is system memory available for UEFI NextHob.ResourceDescriptor->PhysicalStart += PcdGet32(PcdFdSize); NextHob.ResourceDescriptor->ResourceLength -= PcdGet32(PcdFdSize); } } else { // Create the System Memory HOB for the firmware with the non-present attribute BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY, ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT, PcdGet32(PcdFdBaseAddress), PcdGet32(PcdFdSize)); // Update the HOB NextHob.ResourceDescriptor->ResourceLength = PcdGet32(PcdFdBaseAddress) - NextHob.ResourceDescriptor->PhysicalStart; // If there is some memory available on the top of the FD then create a HOB if (FdTop < NextHob.ResourceDescriptor->PhysicalStart + ResourceLength) { // Create the System Memory HOB for the remaining region (top of the FD) BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY, ResourceAttributes, FdTop, ResourceTop - FdTop); } } Found = TRUE; break; } NextHob.Raw = GET_NEXT_HOB (NextHob); } ASSERT(Found); } // Build Memory Allocation Hob InitMmu (); if (FeaturePcdGet (PcdPrePiProduceMemoryTypeInformationHob)) { // Optional feature that helps prevent EFI memory map fragmentation. BuildMemoryTypeInformationHob (); } return EFI_SUCCESS; }
/** This routine is invoked by main entry of PeiMain module during transition from SEC to PEI. After switching stack in the PEI core, it will restart with the old core data. @param SecCoreDataPtr Points to a data structure containing information about the PEI core's operating environment, such as the size and location of temporary RAM, the stack location and the BFV location. @param PpiList Points to a list of one or more PPI descriptors to be installed initially by the PEI core. An empty PPI list consists of a single descriptor with the end-tag EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. As part of its initialization phase, the PEI Foundation will add these SEC-hosted PPIs to its PPI database such that both the PEI Foundation and any modules can leverage the associated service calls and/or code in these early PPIs @param Data Pointer to old core data that is used to initialize the core's data areas. If NULL, it is first PeiCore entering. **/ VOID EFIAPI PeiCore ( IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreDataPtr, IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList, IN VOID *Data ) { PEI_CORE_INSTANCE PrivateData; EFI_SEC_PEI_HAND_OFF *SecCoreData; EFI_SEC_PEI_HAND_OFF NewSecCoreData; EFI_STATUS Status; PEI_CORE_TEMP_POINTERS TempPtr; PEI_CORE_INSTANCE *OldCoreData; EFI_PEI_CPU_IO_PPI *CpuIo; EFI_PEI_PCI_CFG2_PPI *PciCfg; EFI_HOB_HANDOFF_INFO_TABLE *HandoffInformationTable; EFI_PEI_TEMPORARY_RAM_DONE_PPI *TemporaryRamDonePpi; UINTN Index; // // Retrieve context passed into PEI Core // OldCoreData = (PEI_CORE_INSTANCE *) Data; SecCoreData = (EFI_SEC_PEI_HAND_OFF *) SecCoreDataPtr; // // Perform PEI Core phase specific actions. // if (OldCoreData == NULL) { // // If OldCoreData is NULL, means current is the first entry into the PEI Core before memory is available. // ZeroMem (&PrivateData, sizeof (PEI_CORE_INSTANCE)); PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE; CopyMem (&PrivateData.ServiceTableShadow, &gPs, sizeof (gPs)); } else { // // Memory is available to the PEI Core. See if the PEI Core has been shadowed to memory yet. // if (OldCoreData->ShadowedPeiCore == NULL) { // // Fixup the PeiCore's private data // OldCoreData->Ps = &OldCoreData->ServiceTableShadow; OldCoreData->CpuIo = &OldCoreData->ServiceTableShadow.CpuIo; if (OldCoreData->HeapOffsetPositive) { OldCoreData->HobList.Raw = (VOID *)(OldCoreData->HobList.Raw + OldCoreData->HeapOffset); OldCoreData->UnknownFvInfo = (PEI_CORE_UNKNOW_FORMAT_FV_INFO *) ((UINT8 *) OldCoreData->UnknownFvInfo + OldCoreData->HeapOffset); OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->CurrentFvFileHandles + OldCoreData->HeapOffset); OldCoreData->PpiData.PpiListPtrs = (PEI_PPI_LIST_POINTERS *) ((UINT8 *) OldCoreData->PpiData.PpiListPtrs + OldCoreData->HeapOffset); OldCoreData->Fv = (PEI_CORE_FV_HANDLE *) ((UINT8 *) OldCoreData->Fv + OldCoreData->HeapOffset); for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) { OldCoreData->Fv[Index].PeimState = (UINT8 *) OldCoreData->Fv[Index].PeimState + OldCoreData->HeapOffset; OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->Fv[Index].FvFileHandles + OldCoreData->HeapOffset); } OldCoreData->FileGuid = (EFI_GUID *) ((UINT8 *) OldCoreData->FileGuid + OldCoreData->HeapOffset); OldCoreData->FileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->FileHandles + OldCoreData->HeapOffset); } else { OldCoreData->HobList.Raw = (VOID *)(OldCoreData->HobList.Raw - OldCoreData->HeapOffset); OldCoreData->UnknownFvInfo = (PEI_CORE_UNKNOW_FORMAT_FV_INFO *) ((UINT8 *) OldCoreData->UnknownFvInfo - OldCoreData->HeapOffset); OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->CurrentFvFileHandles - OldCoreData->HeapOffset); OldCoreData->PpiData.PpiListPtrs = (PEI_PPI_LIST_POINTERS *) ((UINT8 *) OldCoreData->PpiData.PpiListPtrs - OldCoreData->HeapOffset); OldCoreData->Fv = (PEI_CORE_FV_HANDLE *) ((UINT8 *) OldCoreData->Fv - OldCoreData->HeapOffset); for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) { OldCoreData->Fv[Index].PeimState = (UINT8 *) OldCoreData->Fv[Index].PeimState - OldCoreData->HeapOffset; OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->Fv[Index].FvFileHandles - OldCoreData->HeapOffset); } OldCoreData->FileGuid = (EFI_GUID *) ((UINT8 *) OldCoreData->FileGuid - OldCoreData->HeapOffset); OldCoreData->FileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->FileHandles - OldCoreData->HeapOffset); } // // Fixup for PeiService's address // SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&OldCoreData->Ps); // // Initialize libraries that the PEI Core is linked against // ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&OldCoreData->Ps); // // Update HandOffHob for new installed permanent memory // HandoffInformationTable = OldCoreData->HobList.HandoffInformationTable; if (OldCoreData->HeapOffsetPositive) { HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList + OldCoreData->HeapOffset; } else { HandoffInformationTable->EfiEndOfHobList = HandoffInformationTable->EfiEndOfHobList - OldCoreData->HeapOffset; } HandoffInformationTable->EfiMemoryTop = OldCoreData->PhysicalMemoryBegin + OldCoreData->PhysicalMemoryLength; HandoffInformationTable->EfiMemoryBottom = OldCoreData->PhysicalMemoryBegin; HandoffInformationTable->EfiFreeMemoryTop = OldCoreData->FreePhysicalMemoryTop; HandoffInformationTable->EfiFreeMemoryBottom = HandoffInformationTable->EfiEndOfHobList + sizeof (EFI_HOB_GENERIC_HEADER); // // We need convert MemoryBaseAddress in memory allocation HOBs // ConvertMemoryAllocationHobs (OldCoreData); // // We need convert the PPI descriptor's pointer // ConvertPpiPointers (SecCoreData, OldCoreData); // // After the whole temporary memory is migrated, then we can allocate page in // permanent memory. // OldCoreData->PeiMemoryInstalled = TRUE; // // Indicate that PeiCore reenter // OldCoreData->PeimDispatcherReenter = TRUE; if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 && (OldCoreData->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) { // // if Loading Module at Fixed Address is enabled, allocate the PEI code memory range usage bit map array. // Every bit in the array indicate the status of the corresponding memory page available or not // OldCoreData->PeiCodeMemoryRangeUsageBitMap = AllocateZeroPool (((PcdGet32(PcdLoadFixAddressPeiCodePageNumber)>>6) + 1)*sizeof(UINT64)); } // // Shadow PEI Core. When permanent memory is avaiable, shadow // PEI Core and PEIMs to get high performance. // OldCoreData->ShadowedPeiCore = (PEICORE_FUNCTION_POINTER) (UINTN) PeiCore; if ((HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnS3Boot)) || (HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnBoot))) { OldCoreData->ShadowedPeiCore = ShadowPeiCore (OldCoreData); } // // PEI Core has now been shadowed to memory. Restart PEI Core in memory. // OldCoreData->ShadowedPeiCore (SecCoreData, PpiList, OldCoreData); // // Should never reach here. // ASSERT (FALSE); CpuDeadLoop(); UNREACHABLE (); }
/** Determine whether a given device path is valid. @param DevicePath A pointer to a device path data structure. @param MaxSize The maximum size of the device path data structure. @retval TRUE DevicePath is valid. @retval FALSE DevicePath is NULL. @retval FALSE Maxsize is less than sizeof(EFI_DEVICE_PATH_PROTOCOL). @retval FALSE The length of any node node in the DevicePath is less than sizeof (EFI_DEVICE_PATH_PROTOCOL). @retval FALSE If MaxSize is not zero, the size of the DevicePath exceeds MaxSize. @retval FALSE If PcdMaximumDevicePathNodeCount is not zero, the node count of the DevicePath exceeds PcdMaximumDevicePathNodeCount. **/ BOOLEAN EFIAPI IsDevicePathValid ( IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN UINTN MaxSize ) { UINTN Count; UINTN Size; UINTN NodeLength; // //Validate the input whether exists and its size big enough to touch the first node // if (DevicePath == NULL || (MaxSize > 0 && MaxSize < END_DEVICE_PATH_LENGTH)) { return FALSE; } if (MaxSize == 0) { MaxSize = MAX_UINTN; } for (Count = 0, Size = 0; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) { NodeLength = DevicePathNodeLength (DevicePath); if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { return FALSE; } if (NodeLength > MAX_UINTN - Size) { return FALSE; } Size += NodeLength; // // Validate next node before touch it. // if (Size > MaxSize - END_DEVICE_PATH_LENGTH ) { return FALSE; } if (PcdGet32 (PcdMaximumDevicePathNodeCount) > 0) { Count++; if (Count >= PcdGet32 (PcdMaximumDevicePathNodeCount)) { return FALSE; } } // // FilePath must be a NULL-terminated string. // if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH && DevicePathSubType (DevicePath) == MEDIA_FILEPATH_DP && *(CHAR16 *)((UINT8 *)DevicePath + NodeLength - 2) != 0) { return FALSE; } } // // Only return TRUE when the End Device Path node is valid. // return (BOOLEAN) (DevicePathNodeLength (DevicePath) == END_DEVICE_PATH_LENGTH); }
/** Initial the boot mode related parameters. **/ VOID BmInitialBootModeInfo ( VOID ) { EFI_STATUS Status; EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut; UINTN BootTextColumn; UINTN BootTextRow; if (mBmModeInitialized) { return; } // // After the console is ready, get current video resolution // and text mode before launching setup at first time. // Status = gBS->HandleProtocol ( gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID**)&GraphicsOutput ); if (EFI_ERROR (Status)) { GraphicsOutput = NULL; } Status = gBS->HandleProtocol ( gST->ConsoleOutHandle, &gEfiSimpleTextOutProtocolGuid, (VOID**)&SimpleTextOut ); if (EFI_ERROR (Status)) { SimpleTextOut = NULL; } if (GraphicsOutput != NULL) { // // Get current video resolution and text mode. // mBmBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution; mBmBootVerticalResolution = GraphicsOutput->Mode->Info->VerticalResolution; } if (SimpleTextOut != NULL) { Status = SimpleTextOut->QueryMode ( SimpleTextOut, SimpleTextOut->Mode->Mode, &BootTextColumn, &BootTextRow ); mBmBootTextModeColumn = (UINT32)BootTextColumn; mBmBootTextModeRow = (UINT32)BootTextRow; } // // Get user defined text mode for setup. // mBmSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution); mBmSetupVerticalResolution = PcdGet32 (PcdSetupVideoVerticalResolution); mBmSetupTextModeColumn = PcdGet32 (PcdSetupConOutColumn); mBmSetupTextModeRow = PcdGet32 (PcdSetupConOutRow); mBmModeInitialized = TRUE; }
/* ** Entry point for the LAN9118 driver ** */ EFI_STATUS Lan9118DxeEntry ( IN EFI_HANDLE Handle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; LAN9118_DRIVER *LanDriver; EFI_SIMPLE_NETWORK_PROTOCOL *Snp; EFI_SIMPLE_NETWORK_MODE *SnpMode; LAN9118_DEVICE_PATH *Lan9118Path; EFI_HANDLE ControllerHandle; // The PcdLan9118DxeBaseAddress PCD must be defined ASSERT (PcdGet32 (PcdLan9118DxeBaseAddress) != 0); // Allocate Resources LanDriver = AllocateZeroPool (sizeof (LAN9118_DRIVER)); if (LanDriver == NULL) { return EFI_OUT_OF_RESOURCES; } Lan9118Path = (LAN9118_DEVICE_PATH*)AllocateCopyPool (sizeof (LAN9118_DEVICE_PATH), &Lan9118PathTemplate); if (Lan9118Path == NULL) { return EFI_OUT_OF_RESOURCES; } // Initialize pointers Snp = &(LanDriver->Snp); SnpMode = &(LanDriver->SnpMode); Snp->Mode = SnpMode; // Set the signature of the LAN Driver structure LanDriver->Signature = LAN9118_SIGNATURE; // Assign fields and func pointers Snp->Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; Snp->WaitForPacket = NULL; Snp->Initialize = SnpInitialize; Snp->Start = SnpStart; Snp->Stop = SnpStop; Snp->Reset = SnpReset; Snp->Shutdown = SnpShutdown; Snp->ReceiveFilters = SnpReceiveFilters; Snp->StationAddress = SnpStationAddress; Snp->Statistics = SnpStatistics; Snp->MCastIpToMac = SnpMcastIptoMac; Snp->NvData = SnpNvData; Snp->GetStatus = SnpGetStatus; Snp->Transmit = SnpTransmit; Snp->Receive = SnpReceive; // Start completing simple network mode structure SnpMode->State = EfiSimpleNetworkStopped; SnpMode->HwAddressSize = NET_ETHER_ADDR_LEN; // HW address is 6 bytes SnpMode->MediaHeaderSize = sizeof(ETHER_HEAD); // Not sure of this SnpMode->MaxPacketSize = EFI_PAGE_SIZE; // Preamble + SOF + Ether Frame (with VLAN tag +4bytes) SnpMode->NvRamSize = 0; // No NVRAM with this device SnpMode->NvRamAccessSize = 0; // No NVRAM with this device // // Claim that all receive filter settings are supported, though the MULTICAST mode // is not completely supported. The LAN9118 Ethernet controller is only able to // do a "hash filtering" and not a perfect filtering on multicast addresses. The // controller does not filter the multicast addresses directly but a hash value // of them. The hash value of a multicast address is derived from its CRC and // ranges from 0 to 63 included. // We claim that the perfect MULTICAST filtering mode is supported because // we do not want the user to switch directly to the PROMISCOUS_MULTICAST mode // and thus not being able to take advantage of the hash filtering. // SnpMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS | EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; // We do not intend to receive anything for the time being. SnpMode->ReceiveFilterSetting = 0; // LAN9118 has 64bit hash table, can filter 64 MCast MAC Addresses SnpMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT; SnpMode->MCastFilterCount = 0; ZeroMem (&SnpMode->MCastFilter, MAX_MCAST_FILTER_CNT * sizeof(EFI_MAC_ADDRESS)); // Set the interface type (1: Ethernet or 6: IEEE 802 Networks) SnpMode->IfType = NET_IFTYPE_ETHERNET; // Mac address is changeable as it is loaded from erasable memory SnpMode->MacAddressChangeable = TRUE; // Can only transmit one packet at a time SnpMode->MultipleTxSupported = FALSE; // MediaPresent checks for cable connection and partner link SnpMode->MediaPresentSupported = TRUE; SnpMode->MediaPresent = FALSE; // Set broadcast address SetMem (&SnpMode->BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF); // Power up the device so we can find the MAC address Status = Lan9118Initialize (Snp); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "LAN9118: Error initialising hardware\n")); return EFI_DEVICE_ERROR; } // Assign fields for device path CopyMem (&Lan9118Path->Lan9118.MacAddress, &Snp->Mode->CurrentAddress, NET_ETHER_ADDR_LEN); Lan9118Path->Lan9118.IfType = Snp->Mode->IfType; // Initialise the protocol ControllerHandle = NULL; Status = gBS->InstallMultipleProtocolInterfaces ( &ControllerHandle, &gEfiSimpleNetworkProtocolGuid, Snp, &gEfiDevicePathProtocolGuid, Lan9118Path, NULL ); // Say what the status of loading the protocol structure is if (EFI_ERROR(Status)) { FreePool (LanDriver); } else { LanDriver->ControllerHandle = ControllerHandle; } return Status; }
// PERF_END (NULL, "DXE", NULL, 0); PERF_START (NULL, "BDS", NULL, 0); DEBUG ((EFI_D_INFO, "[Bds] Entry...\n")); PERF_CODE ( BdsAllocateMemoryForPerformanceData (); ); // // Fill in FirmwareVendor and FirmwareRevision from PCDs // FirmwareVendor = (CHAR16 *) PcdGetPtr (PcdFirmwareVendor); gST->FirmwareVendor = AllocateRuntimeCopyPool (StrSize (FirmwareVendor), FirmwareVendor); ASSERT (gST->FirmwareVendor != NULL); gST->FirmwareRevision = PcdGet32 (PcdFirmwareRevision); // // Fixup Tasble CRC after we updated Firmware Vendor and Revision // gST->Hdr.CRC32 = 0; gBS->CalculateCrc32 ((VOID *) gST, sizeof (EFI_SYSTEM_TABLE), &gST->Hdr.CRC32); // // Validate Variable. // BdsFormalizeEfiGlobalVariable (); // // Mark the read-only variables if the Variable Lock protocol exists //
/** Install ACPI Firmware Performance Data Table (FPDT). @return Status code. **/ EFI_STATUS InstallFirmwarePerformanceDataTable ( VOID ) { EFI_STATUS Status; EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol; UINTN Size; UINT8 *SmmBootRecordCommBuffer; EFI_SMM_COMMUNICATE_HEADER *SmmCommBufferHeader; SMM_BOOT_RECORD_COMMUNICATE *SmmCommData; UINTN CommSize; UINTN BootPerformanceDataSize; UINT8 *BootPerformanceData; EFI_SMM_COMMUNICATION_PROTOCOL *Communication; FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable; // // Get AcpiTable Protocol. // Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol); if (EFI_ERROR (Status)) { return Status; } // // Collect boot records from SMM drivers. // SmmBootRecordCommBuffer = NULL; SmmCommData = NULL; Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &Communication); if (!EFI_ERROR (Status)) { // // Initialize communicate buffer // SmmBootRecordCommBuffer = AllocateZeroPool (SMM_BOOT_RECORD_COMM_SIZE); ASSERT (SmmBootRecordCommBuffer != NULL); SmmCommBufferHeader = (EFI_SMM_COMMUNICATE_HEADER*)SmmBootRecordCommBuffer; SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE*)SmmCommBufferHeader->Data; ZeroMem((UINT8*)SmmCommData, sizeof(SMM_BOOT_RECORD_COMMUNICATE)); CopyGuid (&SmmCommBufferHeader->HeaderGuid, &gEfiFirmwarePerformanceGuid); SmmCommBufferHeader->MessageLength = sizeof(SMM_BOOT_RECORD_COMMUNICATE); CommSize = SMM_BOOT_RECORD_COMM_SIZE; // // Get the size of boot records. // SmmCommData->Function = SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE; SmmCommData->BootRecordData = NULL; Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize); ASSERT_EFI_ERROR (Status); if (!EFI_ERROR (SmmCommData->ReturnStatus) && SmmCommData->BootRecordSize != 0) { // // Get all boot records // SmmCommData->Function = SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA; SmmCommData->BootRecordData = AllocateZeroPool(SmmCommData->BootRecordSize); ASSERT (SmmCommData->BootRecordData != NULL); Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize); ASSERT_EFI_ERROR (Status); ASSERT_EFI_ERROR(SmmCommData->ReturnStatus); } } // // Prepare memory for Boot Performance table. // Boot Performance table includes BasicBoot record, and one or more appended Boot Records. // BootPerformanceDataSize = sizeof (BOOT_PERFORMANCE_TABLE) + mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize); if (SmmCommData != NULL) { BootPerformanceDataSize += SmmCommData->BootRecordSize; } // // Try to allocate the same runtime buffer as last time boot. // ZeroMem (&PerformanceVariable, sizeof (PerformanceVariable)); Size = sizeof (PerformanceVariable); Status = gRT->GetVariable ( EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME, &gEfiFirmwarePerformanceGuid, NULL, &Size, &PerformanceVariable ); if (!EFI_ERROR (Status)) { Status = gBS->AllocatePages ( AllocateAddress, EfiReservedMemoryType, EFI_SIZE_TO_PAGES (BootPerformanceDataSize), &PerformanceVariable.BootPerformanceTablePointer ); if (!EFI_ERROR (Status)) { mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) (UINTN) PerformanceVariable.BootPerformanceTablePointer; } } if (mAcpiBootPerformanceTable == NULL) { // // Fail to allocate at specified address, continue to allocate at any address. // mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) FpdtAllocateReservedMemoryBelow4G (BootPerformanceDataSize); } DEBUG ((EFI_D_INFO, "FPDT: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable)); if (mAcpiBootPerformanceTable == NULL) { if (SmmCommData != NULL && SmmCommData->BootRecordData != NULL) { FreePool (SmmCommData->BootRecordData); } if (SmmBootRecordCommBuffer != NULL) { FreePool (SmmBootRecordCommBuffer); } if (mAcpiS3PerformanceTable != NULL) { FreePages (mAcpiS3PerformanceTable, EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE))); } return EFI_OUT_OF_RESOURCES; } // // Prepare Boot Performance Table. // BootPerformanceData = (UINT8 *) mAcpiBootPerformanceTable; // // Fill Basic Boot record to Boot Performance Table. // CopyMem (mAcpiBootPerformanceTable, &mBootPerformanceTableTemplate, sizeof (mBootPerformanceTableTemplate)); BootPerformanceData = BootPerformanceData + mAcpiBootPerformanceTable->Header.Length; // // Fill Boot records from boot drivers. // CopyMem (BootPerformanceData, mBootRecordBuffer, mBootRecordSize); mAcpiBootPerformanceTable->Header.Length += mBootRecordSize; BootPerformanceData = BootPerformanceData + mBootRecordSize; if (SmmCommData != NULL && SmmCommData->BootRecordData != NULL) { // // Fill Boot records from SMM drivers. // CopyMem (BootPerformanceData, SmmCommData->BootRecordData, SmmCommData->BootRecordSize); FreePool (SmmCommData->BootRecordData); mAcpiBootPerformanceTable->Header.Length = (UINT32) (mAcpiBootPerformanceTable->Header.Length + SmmCommData->BootRecordSize); BootPerformanceData = BootPerformanceData + SmmCommData->BootRecordSize; } if (SmmBootRecordCommBuffer != NULL) { FreePool (SmmBootRecordCommBuffer); } // // Save Boot Performance Table address to Variable for use in S4 resume. // PerformanceVariable.BootPerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiBootPerformanceTable; // // Update Boot Performance Table Pointer in template. // mFirmwarePerformanceTableTemplate.BootPointerRecord.BootPerformanceTablePointer = (UINT64) (UINTN) mAcpiBootPerformanceTable; // // Save S3 Performance Table address to Variable for use in S4 resume. // PerformanceVariable.S3PerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiS3PerformanceTable; // // Update S3 Performance Table Pointer in template. // mFirmwarePerformanceTableTemplate.S3PointerRecord.S3PerformanceTablePointer = (UINT64) (UINTN) mAcpiS3PerformanceTable; // // Save Runtime Performance Table pointers to Variable. // Status = gRT->SetVariable ( EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME, &gEfiFirmwarePerformanceGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof (PerformanceVariable), &PerformanceVariable ); ASSERT_EFI_ERROR (Status); // // Publish Firmware Performance Data Table. // FpdtAcpiTableChecksum ((UINT8 *) &mFirmwarePerformanceTableTemplate, mFirmwarePerformanceTableTemplate.Header.Length); Status = AcpiTableProtocol->InstallAcpiTable ( AcpiTableProtocol, &mFirmwarePerformanceTableTemplate, mFirmwarePerformanceTableTemplate.Header.Length, &mFirmwarePerformanceTableTemplateKey ); if (EFI_ERROR (Status)) { FreePages (mAcpiBootPerformanceTable, EFI_SIZE_TO_PAGES (BootPerformanceDataSize)); if (mAcpiS3PerformanceTable != NULL) { FreePages (mAcpiS3PerformanceTable, EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE))); } mAcpiBootPerformanceTable = NULL; mAcpiS3PerformanceTable = NULL; return Status; } // // Free temp Boot record, and update Boot Record to point to Basic Boot performance table. // if (mBootRecordBuffer != NULL) { FreePool (mBootRecordBuffer); } mBootRecordBuffer = (UINT8 *) mAcpiBootPerformanceTable; mBootRecordSize = mAcpiBootPerformanceTable->Header.Length; mBootRecordMaxSize = mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize); return EFI_SUCCESS; }
/** Provides the service of deferring image load based on platform policy control, and installs Deferred Image Load Protocol. @param[in] AuthenticationStatus This is the authentication status returned from the security measurement services for the input file. @param[in] File This is a pointer to the device path of the file that is being dispatched. This will optionally be used for logging. @param[in] FileBuffer File buffer matches the input file device path. @param[in] FileSize Size of File buffer matches the input file device path. @param[in] BootPolicy A boot policy that was used to call LoadImage() UEFI service. @retval EFI_SUCCESS FileBuffer is NULL and current user has permission to start UEFI device drivers on the device path specified by DevicePath. @retval EFI_SUCCESS The file specified by DevicePath and non-NULL FileBuffer did authenticate, and the platform policy dictates that the DXE Foundation may use the file. @retval EFI_SECURITY_VIOLATION FileBuffer is NULL and the user has no permission to start UEFI device drivers on the device path specified by DevicePath. @retval EFI_SECURITY_VIOLATION FileBuffer is not NULL and the user has no permission to load drivers from the device path specified by DevicePath. The image has been added into the list of the deferred images. @retval EFI_ACCESS_DENIED The file specified by File and FileBuffer did not authenticate, and the platform policy dictates that the DXE Foundation many not use File. **/ EFI_STATUS EFIAPI DxeDeferImageLoadHandler ( IN UINT32 AuthenticationStatus, IN CONST EFI_DEVICE_PATH_PROTOCOL *File, IN VOID *FileBuffer, IN UINTN FileSize, IN BOOLEAN BootPolicy ) { EFI_STATUS Status; EFI_USER_PROFILE_HANDLE CurrentUser; UINT32 Policy; UINT32 FileType; // // Ignore if File is NULL. // if (File == NULL) { return EFI_SUCCESS; } // // Check whether user has a logon. // CurrentUser = NULL; if (mUserManager != NULL) { mUserManager->Current (mUserManager, &CurrentUser); if (CurrentUser != NULL) { // // The user is logon; verify the FilePath by current user access policy. // if (!VerifyDevicePath (File)) { DEBUG ((EFI_D_ERROR, "[Security] The image is forbidden to load!\n")); return EFI_SECURITY_VIOLATION; } return EFI_SUCCESS; } } // // Still no user logon. // Check the file type and get policy setting. // FileType = GetFileType (File); Policy = PcdGet32 (PcdDeferImageLoadPolicy); if ((Policy & FileType) == FileType) { // // This file type is secure to load. // return EFI_SUCCESS; } DEBUG ((EFI_D_ERROR, "[Security] No user identified, the image is deferred to load!\n")); PutDefferedImageInfo (File, FileBuffer, FileSize); // // Install the Deferred Image Load Protocol onto a new handle. // if (!mIsProtocolInstalled) { Status = gBS->InstallMultipleProtocolInterfaces ( &mDeferredImageHandle, &gEfiDeferredImageLoadProtocolGuid, &gDeferredImageLoad, NULL ); ASSERT_EFI_ERROR (Status); mIsProtocolInstalled = TRUE; } return EFI_ACCESS_DENIED; }
/** Report status code listener of FPDT. This is used to collect performance data for OsLoaderLoadImageStart and OsLoaderStartImageStart in FPDT. @param[in] CodeType Indicates the type of status code being reported. @param[in] Value Describes the current status of a hardware or software entity. This included information about the class and subclass that is used to classify the entity as well as an operation. @param[in] Instance The enumeration of a hardware or software entity within the system. Valid instance numbers start with 1. @param[in] CallerId This optional parameter may be used to identify the caller. This parameter allows the status code driver to apply different rules to different callers. @param[in] Data This optional parameter may be used to pass additional data. @retval EFI_SUCCESS Status code is what we expected. @retval EFI_UNSUPPORTED Status code not supported. **/ EFI_STATUS EFIAPI FpdtStatusCodeListenerDxe ( IN EFI_STATUS_CODE_TYPE CodeType, IN EFI_STATUS_CODE_VALUE Value, IN UINT32 Instance, IN EFI_GUID *CallerId, IN EFI_STATUS_CODE_DATA *Data ) { EFI_STATUS Status; // // Check whether status code is what we are interested in. // if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) != EFI_PROGRESS_CODE) { return EFI_UNSUPPORTED; } Status = EFI_SUCCESS; if (Value == PcdGet32 (PcdProgressCodeOsLoaderLoad)) { // // Progress code for OS Loader LoadImage. // if (mAcpiBootPerformanceTable == NULL) { return Status; } // // Update OS Loader LoadImage Start for UEFI boot. // mAcpiBootPerformanceTable->BasicBoot.OsLoaderLoadImageStart = GetTimeInNanoSecond (GetPerformanceCounter ()); } else if (Value == PcdGet32 (PcdProgressCodeOsLoaderStart)) { // // Progress code for OS Loader StartImage. // if (mAcpiBootPerformanceTable == NULL) { return Status; } // // Update OS Loader StartImage Start for UEFI boot. // mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart = GetTimeInNanoSecond (GetPerformanceCounter ()); } else if (Value == (EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES)) { // // Progress code for ExitBootServices. // if (mAcpiBootPerformanceTable == NULL) { return Status; } // // Update ExitBootServicesExit for UEFI boot. // mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesExit = GetTimeInNanoSecond (GetPerformanceCounter ()); // // Unregister boot time report status code listener. // mRscHandlerProtocol->Unregister (FpdtStatusCodeListenerDxe); } else if (Data != NULL && CompareGuid (&Data->Type, &gEfiFirmwarePerformanceGuid)) { // // Append one or more Boot records // if (mAcpiBootPerformanceTable == NULL) { // // Append Boot records before FPDT ACPI table is installed. // if (mBootRecordSize + Data->Size > mBootRecordMaxSize) { mBootRecordBuffer = ReallocatePool (mBootRecordSize, mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE, mBootRecordBuffer); ASSERT (mBootRecordBuffer != NULL); mBootRecordMaxSize = mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE; } // // Save boot record into the temp memory space. // CopyMem (mBootRecordBuffer + mBootRecordSize, Data + 1, Data->Size); mBootRecordSize += Data->Size; } else { // // Append Boot records after FPDT ACPI table is installed. // if (mBootRecordSize + Data->Size > mBootRecordMaxSize) { // // No enough space to save boot record. // Status = EFI_OUT_OF_RESOURCES; } else { // // Save boot record into BootPerformance table // CopyMem (mBootRecordBuffer + mBootRecordSize, Data + 1, Data->Size); mBootRecordSize += Data->Size; mAcpiBootPerformanceTable->Header.Length = mBootRecordSize; } } } else { // // Ignore else progress code. // Status = EFI_UNSUPPORTED; } return Status; }
EFI_STATUS EFIAPI InitSpiDevice ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_EVENT Event; CONST FLASH_PART_DESCRIPTION *FlashDescription; UINT64 FlashSize; EFI_HANDLE Handle; EFI_STATUS Status; mNvStorageBase = PcdGet32 (PcdFlashNvStorageVariableBase); // // Locate the SPI controller protocol and save it for later. // DEBUG((EFI_D_INFO, "Locating SPI Controller Protocol.\n")); Status = gBS->LocateProtocol ( &gEfiSpiProtocolGuid, NULL, (VOID **) &mSpiProtocol ); ASSERT_EFI_ERROR(Status); // // Loop through all the flash devices that are supported and see if one will // initialize the SPI Controller interface. // FlashSize = FindFlashSupport ( &JedecIdRead, NULL, &FlashDescription ); if (FlashSize == 0) { DEBUG((EFI_D_ERROR, "No SPI flash part description found!\r\n")); } else { // // Attempt to configure the SPI controller for this device. // DEBUG((EFI_D_INFO, "SPI flash size: %d MBytes\n", DivU64x32(FlashSize, 1024 * 1024 ))); DEBUG((EFI_D_INFO, "Configuring SPI Controller.\n")); Status = SpiFlashInit (FlashDescription); if (!EFI_ERROR (Status)) { // // Publish the SPI Device protocol. // DEBUG((EFI_D_INFO, "Installing SPI Device Protocol.\n")); Handle = NULL; Status = gBS->InstallMultipleProtocolInterfaces ( &Handle, &gSpiDeviceProtocolGuid, &mSpiDevProtocol, NULL ); if (EFI_ERROR (Status)) { return EFI_OUT_OF_RESOURCES; } // // Make sure we can handle virtual address changes. // Event = NULL; Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, SpiDeviceVirtualAddressChangeEvent, NULL, &gEfiEventVirtualAddressChangeGuid, &Event ); return EFI_SUCCESS; } } // // Unable to find a supported SPI device // DEBUG((EFI_D_ERROR, "Unable to configure SPI Controller for SPI device present.\n")); return EFI_UNSUPPORTED; }
/** Stalls the CPU for at least the given number of microseconds. Stalls the CPU for the number of microseconds specified by MicroSeconds. The hardware timer is 32 bits. The maximum possible delay is (0xFFFFFFFF / TimerFrequencyMHz), i.e. ([32bits] / FreqInMHz) For example: +----------------+------------+----------+----------+ | TimerFrequency | MaxDelay | MaxDelay | MaxDelay | | (MHz) | (us) | (s) | (min) | +----------------+------------+----------+----------+ | 1 | 0xFFFFFFFF | 4294 | 71.5 | | 5 | 0x33333333 | 859 | 14.3 | | 10 | 0x19999999 | 429 | 7.2 | | 50 | 0x051EB851 | 86 | 1.4 | +----------------+------------+----------+----------+ If it becomes necessary to support higher delays, then consider using the real time clock. During this delay, the cpu is not yielded to any other process, with one exception: events that are triggered off a timer and which execute at a higher TPL than this function. These events may call MicroSecondDelay (or NanoSecondDelay) to fulfil their own needs. Therefore, this function must be re-entrant, as it may be interrupted and re-started. @param MicroSeconds The minimum number of microseconds to delay. @return The value of MicroSeconds inputted. **/ UINTN EFIAPI MicroSecondDelay ( IN UINTN MicroSeconds ) { UINT64 DelayTicks64; // Convert from microseconds to timer ticks, more bits to detect over-range conditions. UINTN DelayTicks; // Convert from microseconds to timer ticks, native size for general calculations. UINTN StartTicks; // Timer value snapshot at the start of the delay UINTN TargetTicks; // Timer value to signal the end of the delay UINTN CurrentTicks; // Current value of the 64-bit timer value at any given moment // If we snapshot the timer at the start of the delay function then we minimise unaccounted overheads. StartTicks = MmioRead32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_CURRENT_REG); // We are operating at the limit of 32bits. For the range checking work in 64 bits to avoid overflows. DelayTicks64 = MultU64x32((UINT64)MicroSeconds, PcdGet32(PcdSP804TimerFrequencyInMHz)); // We are limited to 32 bits. // If the specified delay is exactly equal to the max range of the timer, // then the start will be equal to the stop plus one timer overflow (wrap-around). // To avoid having to check for that, reduce the maximum acceptable range by 1 tick, // i.e. reject delays equal or greater than the max range of the timer. if (DelayTicks64 >= (UINT64)SP804_MAX_TICKS) { DEBUG((EFI_D_ERROR,"MicroSecondDelay: ERROR: MicroSeconds=%d exceed SP804 count range. Max MicroSeconds=%d\n", MicroSeconds, ((UINTN)SP804_MAX_TICKS/PcdGet32(PcdSP804TimerFrequencyInMHz)))); } ASSERT(DelayTicks64 < (UINT64)SP804_MAX_TICKS); // From now on do calculations only in native bit size. DelayTicks = (UINTN)DelayTicks64; // Calculate the target value of the timer. //Note: SP804 timer is counting down if (StartTicks >= DelayTicks) { // In this case we do not expect a wrap-around of the timer to occur. // CurrentTicks must be less than StartTicks and higher than TargetTicks. // If this is not the case, then the delay has been reached and may even have been exceeded if this // function was suspended by a higher priority interrupt. TargetTicks = StartTicks - DelayTicks; do { CurrentTicks = MmioRead32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_CURRENT_REG); } while ((CurrentTicks > TargetTicks) && (CurrentTicks <= StartTicks)); } else { // In this case TargetTicks is larger than StartTicks. // This means we expect a wrap-around of the timer to occur and we must wait for it. // Before the wrap-around, CurrentTicks must be less than StartTicks and less than TargetTicks. // After the wrap-around, CurrentTicks must be larger than StartTicks and larger than TargetTicks. // If this is not the case, then the delay has been reached and may even have been exceeded if this // function was suspended by a higher priority interrupt. // The order of operations is essential to avoid arithmetic overflow problems TargetTicks = ((UINTN)SP804_MAX_TICKS - DelayTicks) + StartTicks; // First wait for the wrap-around to occur do { CurrentTicks = MmioRead32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_CURRENT_REG); } while (CurrentTicks <= StartTicks); // Then wait for the target do { CurrentTicks = MmioRead32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_CURRENT_REG); } while (CurrentTicks > TargetTicks); } return MicroSeconds; }