/** @file Dxe ResetSystem library implementation. Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include // EfiConvertPointer() #include "ResetSystemAcpiGed.h" /** Modifies the attributes to Runtime type for a page size memory region. @param BaseAddress Specified start address @retval EFI_SUCCESS The attributes were set for the memory region. @retval EFI_INVALID_PARAMETER Length is zero. @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory resource range specified by BaseAddress and Length. @retval EFI_UNSUPPORTED The bit mask of attributes is not support for the memory resource range specified by BaseAddress and Length. @retval EFI_ACCESS_DEFINED The attributes for the memory resource range specified by BaseAddress and Length cannot be modified. @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of the memory resource range. @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is not available yet. **/ STATIC EFI_STATUS SetMemoryAttributesRunTime ( UINTN Address ) { EFI_STATUS Status; EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; Address &= ~EFI_PAGE_MASK; Status = gDS->GetMemorySpaceDescriptor (Address, &Descriptor); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "%a: GetMemorySpaceDescriptor failed\n", __func__)); return Status; } if (Descriptor.GcdMemoryType == EfiGcdMemoryTypeNonExistent) { Status = gDS->AddMemorySpace ( EfiGcdMemoryTypeMemoryMappedIo, Address, EFI_PAGE_SIZE, EFI_MEMORY_UC | EFI_MEMORY_RUNTIME ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "%a: AddMemorySpace failed\n", __func__)); return Status; } Status = gDS->SetMemorySpaceAttributes ( Address, EFI_PAGE_SIZE, EFI_MEMORY_RUNTIME ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "%a:%d SetMemorySpaceAttributes failed\n", __func__, __LINE__)); return Status; } } else if (!(Descriptor.Attributes & EFI_MEMORY_RUNTIME)) { Status = gDS->SetMemorySpaceAttributes ( Address, EFI_PAGE_SIZE, Descriptor.Attributes | EFI_MEMORY_RUNTIME ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "%a:%d SetMemorySpaceAttributes failed\n", __func__, __LINE__)); return Status; } } return EFI_SUCCESS; } /** Find the power manager related info from ACPI table @retval RETURN_SUCCESS Successfully find out all the required information. @retval RETURN_NOT_FOUND Failed to find the required info. **/ STATIC EFI_STATUS GetPowerManagerByParseAcpiInfo ( VOID ) { EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt = NULL; EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp = NULL; EFI_ACPI_DESCRIPTION_HEADER *Xsdt = NULL; EFI_ACPI_DESCRIPTION_HEADER *Rsdt = NULL; UINT32 *Entry32 = NULL; UINTN Entry32Num; UINT32 *Signature = NULL; UINTN Idx; EFI_STATUS Status; Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID **)&Rsdp); if (EFI_ERROR (Status)) { Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **)&Rsdp); } if (EFI_ERROR (Status) || (Rsdp == NULL)) { DEBUG ((DEBUG_ERROR, "EFI_ERROR or Rsdp == NULL\n")); return RETURN_NOT_FOUND; } Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->RsdtAddress; Entry32 = (UINT32 *)(UINTN)(Rsdt + 1); Entry32Num = (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) >> 2; for (Idx = 0; Idx < Entry32Num; Idx++) { Signature = (UINT32 *)(UINTN)Entry32[Idx]; if (*Signature == EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) { Fadt = (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature; DEBUG ((DEBUG_INFO, "Found Fadt in Rsdt\n")); goto Done; } } Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)Rsdp->XsdtAddress; Entry32 = (UINT32 *)(Xsdt + 1); Entry32Num = (Xsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) >> 2; for (Idx = 0; Idx < Entry32Num; Idx++) { Signature = (UINT32 *)(UINTN)Entry32[Idx]; if (*Signature == EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) { Fadt = (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *)Signature; DEBUG ((DEBUG_INFO, "Found Fadt in Xsdt\n")); goto Done; } } DEBUG ((DEBUG_ERROR, " Fadt Not Found\n")); return RETURN_NOT_FOUND; Done: mPowerManager.ResetRegAddr = Fadt->ResetReg.Address; mPowerManager.ResetValue = Fadt->ResetValue; mPowerManager.SleepControlRegAddr = Fadt->SleepControlReg.Address; mPowerManager.SleepStatusRegAddr = Fadt->SleepStatusReg.Address; return RETURN_SUCCESS; } /** This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event. It converts a pointer to a new virtual address. @param[in] Event Event whose notification function is being invoked. @param[in] Context Pointer to the notification function's context **/ STATIC VOID ResetSystemLibAddressChangeEvent ( IN EFI_EVENT Event, IN VOID *Context ) { EfiConvertPointer (0, (VOID **)&mPowerManager.SleepControlRegAddr); EfiConvertPointer (0, (VOID **)&mPowerManager.SleepStatusRegAddr); EfiConvertPointer (0, (VOID **)&mPowerManager.ResetRegAddr); } /** Notification function of ACPI Table change. This is a notification function registered on ACPI Table change event. It saves the Century address stored in ACPI FADT table. @param Event Event whose notification function is being invoked. @param Context Pointer to the notification function's context. **/ STATIC VOID AcpiNotificationEvent ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_STATUS Status; Status = GetPowerManagerByParseAcpiInfo (); if (EFI_ERROR (Status)) { return; } DEBUG ((DEBUG_INFO, "%a: sleepControl %llx\n", __func__, mPowerManager.SleepControlRegAddr)); ASSERT (mPowerManager.SleepControlRegAddr); Status = SetMemoryAttributesRunTime (mPowerManager.SleepControlRegAddr); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "%a:%d\n", __func__, __LINE__)); return; } DEBUG ((DEBUG_INFO, "%a: sleepStatus %llx\n", __func__, mPowerManager.SleepStatusRegAddr)); ASSERT (mPowerManager.SleepStatusRegAddr); Status = SetMemoryAttributesRunTime (mPowerManager.SleepStatusRegAddr); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "%a:%d\n", __func__, __LINE__)); return; } DEBUG ((DEBUG_INFO, "%a: ResetReg %llx\n", __func__, mPowerManager.ResetRegAddr)); ASSERT (mPowerManager.ResetRegAddr); Status = SetMemoryAttributesRunTime (mPowerManager.ResetRegAddr); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "%a:%d\n", __func__, __LINE__)); } return; } /** The constructor function to Register ACPI Table change event and Address Change Event. @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS. **/ EFI_STATUS EFIAPI ResetSystemLibConstructor ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_EVENT Event; EFI_EVENT ResetSystemVirtualNotifyEvent; Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_CALLBACK, AcpiNotificationEvent, NULL, &gEfiAcpiTableGuid, &Event ); // // Register SetVirtualAddressMap () notify function // Status = gBS->CreateEvent ( EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, TPL_NOTIFY, ResetSystemLibAddressChangeEvent, NULL, &ResetSystemVirtualNotifyEvent ); ASSERT_EFI_ERROR (Status); return Status; }