/** @file * * Copyright (c) 2018, Hisilicon Limited. All rights reserved. * Copyright (c) 2018, Linaro Limited. All rights reserved. * * SPDX-License-Identifier: BSD-2-Clause-Patent * **/ #include #include #include #include #include #include #include "Bert/Bert.h" #include "Einj/Einj.h" #include "ErrorSource/Ghes.h" #include "Erst/Erst.h" #include "Hest/Hest.h" #include "OemApeiHi1620.h" VOID GpioCombInit ( UINTN Base, UINT32 Pin ) { UINT32 Val = MmioRead32 (Base + GPIO_INT_MASK); MmioWrite32 (Base + GPIO_INT_MASK, Val | Pin); Val = MmioRead32 (Base + GPIO_INT_EN); MmioWrite32 (Base + GPIO_INT_EN, Val | Pin); Val = MmioRead32 (Base + GPIO_SWPORT_DDR); MmioWrite32 (Base + GPIO_SWPORT_DDR, Val & (~Pin)); Val = MmioRead32 (Base + GPIO_INT_TYPE); MmioWrite32 (Base + GPIO_INT_TYPE, Val & (~Pin)); Val = MmioRead32 (Base + GPIO_INT_POLARITY); MmioWrite32 (Base + GPIO_INT_POLARITY, Val | Pin); Val = MmioRead32 (Base + GPIO_LS_SYNC); MmioWrite32 (Base + GPIO_LS_SYNC, Val & (~Pin)); MmioWrite32 (Base + GPIO_INT_COMB, 1); return; } /************************************************ *************** HEST *************** ************************************************/ /***************************************************************************** * @param EFI_ACPI_6_1_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE* GhesV2,Vector of GhesV2 * @param UINT8 NumOfGhesV2 * @param_out * @retval EFI_STATUS *****************************************************************************/ EFI_STATUS GhesV2ContextForHest ( IN EFI_ACPI_6_1_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE GhesV2[MAX_GHES], IN UINT8 NumOfGhesV2 ) { // ensuce the size is expected if ((GhesV2 == NULL) || (NumOfGhesV2 != MAX_GHES)) { return EFI_INVALID_PARAMETER; } UINT8 NumOfBlockPerGhes = 1; UINT8 Iter = 0; UINT32 BlockMemorySize; UINT32 ErrorSeverityArray[MAX_GHES] = { EFI_ACPI_6_2_ERROR_SEVERITY_CORRECTABLE, EFI_ACPI_6_2_ERROR_SEVERITY_FATAL, EFI_ACPI_6_2_ERROR_SEVERITY_CORRECTED}; VOID *ErrorBlockHead; VOID *ErrorBlock; VOID *BlockMemory; GHES_REGISTER *GhesRegisters; EFI_STATUS Status = EFI_SUCCESS; BlockMemorySize = MAX_GHES * (sizeof (GHES_REGISTER) + NumOfBlockPerGhes * GENERIC_HARDWARE_ERROR_BLOCK_SIZE); Status = gBS->AllocatePool ( EfiReservedMemoryType, BlockMemorySize, &BlockMemory ); if (EFI_ERROR (Status)) { return Status; } gBS->SetMem (BlockMemory, BlockMemorySize, 0); GhesRegisters = BlockMemory; ErrorBlockHead = BlockMemory + MAX_GHES * sizeof (GHES_REGISTER); ErrorBlock = ErrorBlockHead; for (Iter = 0; Iter < MAX_GHES; Iter++) { GhesV2Initial (&GhesV2[Iter], GENERIC_HARDWARE_ERROR_BLOCK_SIZE); GhesV2AddNotification (&GhesV2[Iter], EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_GSIV); ErrorBlockInitial (ErrorBlock, ErrorSeverityArray[Iter]); GhesV2LinkErrorBlock (&GhesV2[Iter], &GhesRegisters[Iter], ErrorBlock); ErrorBlock += GhesV2[Iter].ErrorStatusBlockLength; } return EFI_SUCCESS; } /***************************************************************************** * @param EFI_ACPI_6_1_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE* GhesV2,Vector of GhesV2 * @param UINT8 NumOfGhesV2 * @param_out * @retval EFI_STATUS *****************************************************************************/ EFI_STATUS GhesV1ContextForHest ( IN EFI_ACPI_6_1_GENERIC_HARDWARE_ERROR_SOURCE_STRUCTURE GhesV1[MAX_GHES], IN UINT8 NumOfGhesV1 ) { // ensuce the size is expected if ((GhesV1 == NULL) || (NumOfGhesV1 != MAX_GHES)) { return EFI_INVALID_PARAMETER; } UINT8 NumOfBlockPerGhes = 1; UINT8 Iter = 0; UINT32 BlockMemorySize = MAX_GHES * (sizeof (UINT64) + NumOfBlockPerGhes * GENERIC_HARDWARE_ERROR_BLOCK_SIZE); UINT32 ErrorSeverityArray[MAX_GHES] = { EFI_ACPI_6_2_ERROR_SEVERITY_CORRECTABLE, EFI_ACPI_6_2_ERROR_SEVERITY_FATAL, EFI_ACPI_6_2_ERROR_SEVERITY_CORRECTED}; VOID *ErrorBlockHead; VOID *ErrorBlock; VOID *BlockMemory; UINT64 *ptrBlockAddress; EFI_STATUS Status = EFI_SUCCESS; Status = gBS->AllocatePool ( EfiReservedMemoryType, BlockMemorySize, &BlockMemory ); if (EFI_ERROR (Status)) { return Status; } gBS->SetMem (BlockMemory, BlockMemorySize, 0); ptrBlockAddress = BlockMemory; ErrorBlockHead = BlockMemory + MAX_GHES * sizeof (UINT64); ErrorBlock = ErrorBlockHead; for (Iter = 0; Iter < MAX_GHES; Iter++) { GhesV1Initial (&GhesV1[Iter], GENERIC_HARDWARE_ERROR_BLOCK_SIZE); GhesV1AddNotification (&GhesV1[Iter], EFI_ACPI_6_1_HARDWARE_ERROR_NOTIFICATION_GSIV); ErrorBlockInitial (ErrorBlock, ErrorSeverityArray[Iter]); GhesV1LinkErrorBlock (&GhesV1[Iter], &ptrBlockAddress[Iter], ErrorBlock); ErrorBlock += GhesV1[Iter].ErrorStatusBlockLength; } return EFI_SUCCESS; } VOID OemHestInitialNotification () { // GPIO init // use int_msk to simulate UINTN Base = IOMUX_REG_BASE; //GPIO9, in document 'PhosphorV680 Totemiomux' iomg051, //Set GPIO9 to pad_ex_int1 MmioWrite32 (Base + IOMG051, PAD_EX_INT1); return; } VOID OemEinjInitialNotification () { UINTN Base = IOMUX_REG_BASE; //use TB_GPIO_PIN10 for EINJ MmioWrite32 (Base + IOMG052, PAD_EX_INT1); return; } EFI_STATUS OemInitHestTable ( IN EFI_HANDLE ImageHandle ) { EFI_STATUS Status = EFI_SUCCESS; HEST_CONTEXT HestContext; EFI_ACPI_6_1_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE GhesV2[MAX_GHES]; Status = HestHeaderCreator (&HestContext, HEST_TABLE_SIZE); if (EFI_ERROR (Status)) { return Status; } Status = GhesV2ContextForHest(GhesV2, MAX_GHES); if (EFI_ERROR (Status)) { return Status; } Status |= HestAddErrorSourceDescriptor ( &HestContext, &GhesV2[0], sizeof (EFI_ACPI_6_1_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE) ); mApeiTrustedfirmwareData->HestRecoverableErrorGhesV2 = HestContext.KeyErrorSource; Status |= HestAddErrorSourceDescriptor ( &HestContext, &GhesV2[1], sizeof (EFI_ACPI_6_1_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE) ); mApeiTrustedfirmwareData->HestFatalErrorGhesV2 = HestContext.KeyErrorSource; Status |= HestAddErrorSourceDescriptor ( &HestContext, &GhesV2[2], sizeof (EFI_ACPI_6_1_GENERIC_HARDWARE_ERROR_SOURCE_VERSION_2_STRUCTURE) ); mApeiTrustedfirmwareData->HestCorrectedErrorGhesV2 = HestContext.KeyErrorSource; OemHestInitialNotification (); HestSetAcpiTable (&HestContext); return Status; } /************************************************ *************** BERT *************** ************************************************/ EFI_STATUS OemInitBertTable ( IN EFI_HANDLE ImageHandle ) { BERT_CONTEXT Context; BOOLEAN Status; Status = BertHeaderCreator (&Context, BOOT_ERROR_REGION_SIZE); if (EFI_ERROR (Status)) { return Status; } ErrorBlockInitial (Context.Block, EFI_ACPI_6_2_ERROR_SEVERITY_NONE); BertSetAcpiTable (&Context); DEBUG ((DEBUG_INFO, "[%a]:[%dL]: %r\n", __FUNCTION__, __LINE__, Status)); return EFI_SUCCESS; } /************************************************ *************** EINJ *************** ************************************************/ EFI_STATUS OemEinjConfigExecuteOperationEntry ( EINJ_CONTEXT *Context ) { EFI_ACPI_6_0_EINJ_INJECTION_INSTRUCTION_ENTRY* KeyEntry = Context->ExecuteOperationEntry; OemEinjInitialNotification (); //use TB_GPIO_PIN10 for EINJ KeyEntry->RegisterRegion.Address = PcdGet64 (PcdCpldBaseAddress) + CPLD_GPIO10_INT_OFFSET; KeyEntry->Mask = CPLD_MASK; KeyEntry->Value = CPLD_VALUE; return EFI_SUCCESS; } EFI_STATUS OemInitEinjTable ( ) { EFI_STATUS Status; EINJ_CONTEXT Context; Status = EinjHeaderCreator (&Context); if (EFI_ERROR (Status)) { return Status; } (VOID)EinjConfigErrorInjectCapability (&Context, 0xFFF);// TBD (VOID)OemEinjConfigExecuteOperationEntry (&Context); EinjSetAcpiTable (&Context); DEBUG ((DEBUG_INFO, "[%a]:[%dL]: %d\n", __FUNCTION__, __LINE__, Status)); return EFI_SUCCESS; } /************************************************ *************** ERST *************** ************************************************/ EFI_STATUS OemErstConfigExecuteOperationEntry ( ERST_BOOT_CONTEXT *Context ) { EFI_ACPI_6_1_ERST_SERIALIZATION_INSTRUCTION_ENTRY *KeyEntry; KeyEntry = Context->ExecuteOperationEntry; KeyEntry->RegisterRegion.Address = GPIO1_BASE + GPIO_INT_MASK; KeyEntry->Value = 0x10; KeyEntry->Mask = 0xFFFFFFFF; GpioCombInit (GPIO1_BASE, 0xFFFF); return EFI_SUCCESS; } BOOLEAN GetNvRamRegion ( OUT VOID **NvRamAddrRange, OUT UINT64 *NvRamAddrRangeLength ) { UINT32 Store = ERST_RECORD_STORE_IN_MEM; switch (Store) { case (ERST_RECORD_STORE_IN_NVRAM): break; case (ERST_RECORD_STORE_IN_MEM): * NvRamAddrRangeLength = ERST_DATASTORE_SIZE; * NvRamAddrRange = AllocateReservedZeroPool (ERST_DATASTORE_SIZE); break; case (ERST_RECORD_STORE_IN_SPI_FLASH): break; default: ; } return TRUE; } /***OEM***/ EFI_STATUS OemInitErstTable ( ) { EFI_STATUS Status = ERST_STATUS_SUCCESS; ERST_BOOT_CONTEXT Context; UINT64 BufferSize = ERST_DATASTORE_SIZE; VOID *NvRamAddrRange; UINT64 NvRamAddrRangeLength; UINT64 NvRamAllRecordLength; GetNvRamRegion (&NvRamAddrRange, &NvRamAddrRangeLength); NvRamAllRecordLength = 0; Status = ErstHeaderCreator ( &Context, BufferSize, NvRamAddrRange, NvRamAllRecordLength, NvRamAddrRangeLength); OemErstConfigExecuteOperationEntry (&Context); mApeiTrustedfirmwareData->ErstContext = (VOID*)Context.Rt; ErstSetAcpiTable (&Context); return Status; };