From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM12-DM6-obe.outbound.protection.outlook.com (NAM12-DM6-obe.outbound.protection.outlook.com [40.107.243.130]) by mx.groups.io with SMTP id smtpd.web11.255.1623775661629118019 for ; Tue, 15 Jun 2021 09:47:41 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@os.amperecomputing.com header.s=selector2 header.b=D/og1Oif; spf=pass (domain: os.amperecomputing.com, ip: 40.107.243.130, mailfrom: nhi@os.amperecomputing.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=N3fhDb9Jeyny6G+r7uvFuO7Auf3ZRDZJpB4MjE1gEzwKYlqDChHV8fofy7u44AcLuAN9JWw/+IEcjG+Lpcyk8saG60UB3rytepWZOmFr8dFseUXX5W7H5qo9eaGrmDLVqA+1sT4gbDF/Gc8PzHJC5XBsS3/RPm2dZjkftyVpuydPAEyfosk7IghZcS5LnL8UAOgOwZYcFD2qnxTw5wK+MwNWOuklGCLvW3+WC2F6XygGtzyKsaKYx8QCmQV2mVV6N5EQLV8vzfCQ3E42qdPXGWt7d42mjv1+Lmg6Cm5ClQ6HFeZKo61JDn5tuMbNSMne+jbq1J+bB+hBG12jMzUAhQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=+HrOcKakGomKmtFUgKy9IcKJCH6kBqsvfzAsQZv21aE=; b=dl+5xqLes20QbzXq8tRr2DcAKY/fyrPCsWsLYaf1T5qn9M6g4fYBVrsrwBRjgmStqBrMJ7/d6p2ls1TMuECymCELnLZboqMYzFNDgDrWerq3TXj+fks8cnPXgOhrH9pzsi7PGzHxZnpOL+yzbEA7OBlbtl7YaL/2mn47O6s7FXaLQeypTc80EJ2zLYmgVXkUiSxYpfCmwra5fjuczeTFETaMe4LSAXU9WE+nvxsmFelAIBfwn420aDJyikURTa7zsvjyhsfsXwaM3OLozwFZkde9pR+z56XjSmW5IgIvDLcuFkyCI4d4cjFYPFBIjDTixDfwYMUzcULIHowuoVIITw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=os.amperecomputing.com; dmarc=pass action=none header.from=os.amperecomputing.com; dkim=pass header.d=os.amperecomputing.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=os.amperecomputing.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=+HrOcKakGomKmtFUgKy9IcKJCH6kBqsvfzAsQZv21aE=; b=D/og1OifH2x1hF5UhD789/vFH7vxHBnJAGFEpWHKhkErJeuNBeVUOGyW3f2S2MZDHcxVY31mrhZp2a0365LpMfnbZd4EOPdQyH7sQFhhlNRqMiI5JRZap6LGKGMu95UzITkTRchil4Zen9VZHdiu7XbIy2xjG6yfRoBFSDE9Ptk= Authentication-Results: intel.com; dkim=none (message not signed) header.d=none;intel.com; dmarc=none action=none header.from=os.amperecomputing.com; Received: from DM6PR01MB5849.prod.exchangelabs.com (2603:10b6:5:205::20) by DM6PR01MB3946.prod.exchangelabs.com (2603:10b6:5:87::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4219.22; Tue, 15 Jun 2021 16:47:40 +0000 Received: from DM6PR01MB5849.prod.exchangelabs.com ([fe80::4d8d:74e3:6747:75a2]) by DM6PR01MB5849.prod.exchangelabs.com ([fe80::4d8d:74e3:6747:75a2%7]) with mapi id 15.20.4219.025; Tue, 15 Jun 2021 16:47:40 +0000 Subject: Re: [edk2-platforms][PATCH v2 04/32] AmperePlatformPkg: Add FailSafe and WDT support To: Leif Lindholm Cc: devel@edk2.groups.io, Thang Nguyen , Chuong Tran , Phong Vo , Michael D Kinney , Ard Biesheuvel , Nate DeSimone References: <20210526100724.5359-1-nhi@os.amperecomputing.com> <20210526100724.5359-6-nhi@os.amperecomputing.com> <20210604231251.qdmtx7tzf2ph4d2p@leviathan> From: "Nhi Pham" Message-ID: Date: Tue, 15 Jun 2021 23:47:29 +0700 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:78.0) Gecko/20100101 Thunderbird/78.11.0 In-Reply-To: <20210604231251.qdmtx7tzf2ph4d2p@leviathan> X-Originating-IP: [116.110.40.240] X-ClientProxiedBy: HKAPR03CA0001.apcprd03.prod.outlook.com (2603:1096:203:c8::6) To DM6PR01MB5849.prod.exchangelabs.com (2603:10b6:5:205::20) Return-Path: nhi@os.amperecomputing.com MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from [192.168.1.7] (116.110.40.240) by HKAPR03CA0001.apcprd03.prod.outlook.com (2603:1096:203:c8::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4242.9 via Frontend Transport; Tue, 15 Jun 2021 16:47:36 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 04766ba1-c3b9-4d33-1a19-08d9301d497c X-MS-TrafficTypeDiagnostic: DM6PR01MB3946: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:765; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 8kSnF41kzqbuN6cZn5pA2kZg/1LlebiqfI2EYDu+WWP0MliC2zwXn5pvauowccnH9Qp3GQ8xbHFdavOjWSak/GB2YqK9CGSS/F1gqsMpGoOXLkMeLyrBq/382y0Kz978qlp8uPhEVZUgW1ENTalk07cR2iSjcw438Cqc7W8tsB37J90MZXZb/xpM+Fi+pJL5zjlmqqQ4/8KtZ2miOiREe6zuekw7wqxTfaZE5sXnjYrr/jAtTv0GkTuxO1NtGdqFrL1yhmQ0FGuR30QV/8T+ESCd6kizwLE+bLacTarT26nH37ymvVHEZajNJqnlx/Y2IdG1nePbgmWtJu5FO40qByvOUu0+NAmPcniICxYtlst+mD1+qgCX6I6JuG9gGOvHzuJChb2Q68gg4K3/0u0vkybwxiwmJciIaXi9r8QsNOVTmzxI3yjI+VTuzwA+76xSo+Xh4NLzHEs0AZocX/5VswSNvy3PSAMxROp5fAm0cPmNG/YWiE/Nfdin34wsl5Fn5qdyQAAVe3s21W5e/AbaYiuOPOYPRonyc+Cjt5ihtEG79PqO1NcNNw4r3g4ftPrj511wX6vfvtd10kFSjdUp3LlKXsbRTKTRzAzZQL4FDToP06tmN97UVo33FOaP20D7H70/Wd8F1x0pWC2szMQ6V9sczk6yU6+BmQJV6HdyPfVvUM2mJe+1CjHI/2c2hEotHqymAXUl8l/gM3jb7c5qVBlrN0Iwkv36/J4lsGh2CQHoR6SPGWrYKZlCciFUtSdN X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DM6PR01MB5849.prod.exchangelabs.com;PTR:;CAT:NONE;SFS:(4636009)(346002)(136003)(376002)(366004)(39840400004)(396003)(31696002)(86362001)(8936002)(16526019)(31686004)(6916009)(186003)(316002)(83380400001)(5660300002)(6486002)(52116002)(2616005)(54906003)(6666004)(478600001)(66476007)(26005)(38100700002)(2906002)(16576012)(53546011)(8676002)(30864003)(4326008)(19627235002)(66946007)(38350700002)(956004)(66556008)(45980500001)(43740500002)(44824005);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?L1VkT2tSam1PUG1vWGdkTnlzNlBwVTR5UlFseDVPd00vdkR2YzNwd21Zd3ZH?= =?utf-8?B?MEJadnBiK0gzaU9lQTFnM1FGWEE1aGxBclQxWVZjaGxPSy9kR0lydHBxb0Fy?= =?utf-8?B?VUkxTFZQWUhkRVlvczIvSDhudkd3N1lsS3A4dlZ0d2RNaHd0L0l6YVhpa3Rh?= =?utf-8?B?cEtIdDlRcTJaSTQvZ1FpWTlUek05cTlGazNLZXRwbkFQeEs1U1ozM2U3U09Z?= =?utf-8?B?a1ltZ05ZdHF0elYza0prcHU0K1RkZ0lhWWNMa3lBYVo1b1I1b0tWYloydVNw?= =?utf-8?B?WHZ1RGRhR2RjTURDYVhQSHhtUThJMGVhSUd0VHMzTDU0NmEyNDIzeWhMV2pi?= =?utf-8?B?WGZJVWJYa2pCSGxxVCtyU0FnY3ZEQnNuZmJYbE9BWVFKSDg2bFRTcDlqVDZz?= =?utf-8?B?cmVCazFBNW40N2Uvak9PcG81SnR1MXdLVjFOSEJHUS8zc1hmM1hxUVdNaXpL?= =?utf-8?B?bUhEQkpRQ3VBM0dCSHlzSGpDN3plSkI0UndvVjB5Z1lTOVViQURZQ1J0ODZ3?= =?utf-8?B?Y3pIbVlHNEdWUFNFYkU3cC9xWkpsNFRUL1lLVnVLTDRsNmhMWndmUlZBdnU2?= =?utf-8?B?S08ycU94SXVsRklmS2UwRCs3TndRSHpHQi8xSVgrTE1iUGlqSEZxSExDU1JH?= =?utf-8?B?eHdweUZhZG5CTFFLWW04Vk9PUklvWEFkWVF3WlU1V1NDMWdFMGFxTnRDK0J6?= =?utf-8?B?bC8xU2JwRjZpMjJNM1ZCT0thYzlnN3U2WVNyYVA4VVJWVGdsQStzRm5JcDdD?= =?utf-8?B?NG9MQVcyN3dXQTFJOTF4OEdSMTd5TWFmM3pVL2J1Z3JJZ1pDUjR5N1BhbG9y?= =?utf-8?B?Wk90VkZUR3dlbDlHUUtUaUNJSW9FZEVldUFsaE9rei8rR0ErQ1FWdnBFTFNm?= =?utf-8?B?enlFVlNYVGR2d3gxWEZONGFVZG5CR3NReG5Zb0tybEdSSm9EeTA1dklTV2lY?= =?utf-8?B?bnVDaE5ZN0hvM3lHb2ovamxSMUN5b0VpayszbFFVSjdkVE9wNHluNEZnWTU4?= =?utf-8?B?YzltVXgwYk5BanJHL3I0WkN4YkExNmFxai9aWEViSW13QjlMbjlqd3lYdXVo?= =?utf-8?B?R3JHaStocHpscE5uL2xVLzNlWlNNdEgxNUdBWTJ5aVI3R2VmcjlaRkZTNyt6?= =?utf-8?B?NXpoMzl2V2hUVHp4LytmV0N1WkJCVW1vVTNjYTVvaDQ1Q2R5UCtMSkNPN3Fi?= =?utf-8?B?VU1HbGdJY0JSZklnNnJqalRKOUpQNnhSS3FJdy9FMjZzd283WlE5ZkpHa0pP?= =?utf-8?B?KzFHek1kOGJTUnorcFhmZW55SmhJWnpzSE10V1pwOFdjaHdSTjB4ZUpHdnJ2?= =?utf-8?B?R1hFUTM3VnZxS2lhQmc5S3hFS2VUNEI4K3V2aCswczNJVndFdmJQSXhDSUFU?= =?utf-8?B?QURVdGNWV1J0aWlBUkduSU9MVTBlN0NpNDVBRGk5aHNoVHVQdmNsaW5nRElq?= =?utf-8?B?UXliMERiR2ZnMFJ0K1J2VFpiVVozYlovMnBWMzJkMTVodWo1UmdiVVNubitX?= =?utf-8?B?eDZpUW54VkxSUEM2KzlBWVVMTUR6YUpCR1RUOEVLdW1ITENzd0ZxeUlsUkRB?= =?utf-8?B?WXZxZk5mcUJ0eDNsOUMrYzBpbXNrUFJid3prVVpoemJHRkdQYU5OdVQ2WSsv?= =?utf-8?B?WURDdFJ1L2dSaU1FMmhRSkdPYStLRU1UbGoySWMrOWxURUl0QTVzWjJkMGNp?= =?utf-8?B?d1RyV2dVNVR6SmxoNWxqMGlIRkVFVUx3SStDMjdlQk1aRzBEanFacnJ4TDAx?= =?utf-8?Q?XMOHeflK+ED+s0iQgB8wffKwdy783dfy3wpxgwN?= X-OriginatorOrg: os.amperecomputing.com X-MS-Exchange-CrossTenant-Network-Message-Id: 04766ba1-c3b9-4d33-1a19-08d9301d497c X-MS-Exchange-CrossTenant-AuthSource: DM6PR01MB5849.prod.exchangelabs.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Jun 2021 16:47:39.7908 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3bc2b170-fd94-476d-b0ce-4229bdc904a7 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: SoihGMkTFvD9kD5QiW8KumcNb20P7+pmWKd4EqED517Uon1Go/CIbvDakML/Vk8i086GQ7ot+S9t+A/KLoU1O7gArrtVAciS4mFOH4ofFWc= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR01MB3946 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Content-Language: en-US Hi Leif, On 6/5/21 06:12, Leif Lindholm wrote: > On Wed, May 26, 2021 at 17:06:56 +0700, Nhi Pham wrote: >> The FailSafeDxe driver reverts the system's configuration to known good >> values if the system fails to boot up multiple times. It also implements >> the Watchdog Timer Architectural Protocol to reset the system if it >> hangs. >> >> By default, when system starts, it configures the secure watchdog timer >> with a default value of 5 minutes. If the system boots up cleanly to the >> considered good stage, the counter is cleared as it indicates FailSafe >> monitor (ATF) that has booted up successfully. If the timer expires, it >> is considered a failed boot and system is rebooted. >> >> Cc: Thang Nguyen >> Cc: Chuong Tran >> Cc: Phong Vo >> Cc: Leif Lindholm >> Cc: Michael D Kinney >> Cc: Ard Biesheuvel >> Cc: Nate DeSimone >> >> Signed-off-by: Nhi Pham >> --- >> Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc | 1 - >> Platform/Ampere/JadePkg/Jade.dsc | 9 + >> Platform/Ampere/JadePkg/Jade.fdf | 6 +- >> Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.inf | 54 +++ >> Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafe.h | 20 ++ >> Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/Watchdog.h | 29 ++ >> Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.c | 184 ++++++++++ >> Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/Watchdog.c | 357 ++++++++++++++++++++ >> 8 files changed, 658 insertions(+), 2 deletions(-) >> >> diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc >> index 0332473b59b0..6a6f72e995af 100755 >> --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc >> +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc >> @@ -585,7 +585,6 @@ [Components.common] >> # Timer >> # >> ArmPkg/Drivers/TimerDxe/TimerDxe.inf >> - MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf > It's not clear from the commit message why this should happen. > >> >> # >> # ARM GIC Dxe >> diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc >> index f68af24a0d78..f92855af99ab 100755 >> --- a/Platform/Ampere/JadePkg/Jade.dsc >> +++ b/Platform/Ampere/JadePkg/Jade.dsc >> @@ -75,6 +75,11 @@ [LibraryClasses] >> # >> RealTimeClockLib|EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf >> >> + # >> + # Library for FailSafe support >> + # >> + FailSafeLib|Platform/Ampere/AmperePlatformPkg/Library/FailSafeLib/FailSafeLib.inf >> + >> ################################################################################ >> # >> # Specific Platform Pcds >> @@ -98,3 +103,7 @@ [PcdsFixedAtBuild.common] >> # >> ################################################################################ >> [Components.common] >> + # >> + # FailSafe and Watchdog Timer >> + # >> + Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.inf >> diff --git a/Platform/Ampere/JadePkg/Jade.fdf b/Platform/Ampere/JadePkg/Jade.fdf >> index 905289844378..80a86d7c1156 100755 >> --- a/Platform/Ampere/JadePkg/Jade.fdf >> +++ b/Platform/Ampere/JadePkg/Jade.fdf >> @@ -185,7 +185,11 @@ [FV.FvMain] >> # Timer >> # >> INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf >> - INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf > It's not clear from the commit message why this should happen. The Watchdog protocol which is implemented in this Failsafe driver will replace the WatchdogTimer.inf. I will update the commit message to clarify this. Best regards, Nhi > > / > Leif > >> + >> + # >> + # FailSafe and Watchdog Timer >> + # >> + INF Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.inf >> >> # >> # ARM GIC Dxe >> diff --git a/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.inf b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.inf >> new file mode 100755 >> index 000000000000..60de10c95c85 >> --- /dev/null >> +++ b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.inf >> @@ -0,0 +1,54 @@ >> +## @file >> +# >> +# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.
>> +# >> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> +# >> +## >> + >> +[Defines] >> + INF_VERSION = 0x0001001B >> + BASE_NAME = FailSafeDxe >> + FILE_GUID = 7BC4F970-B1CF-11E6-80F5-76304DEC7EB7 >> + MODULE_TYPE = DXE_DRIVER >> + VERSION_STRING = 1.0 >> + ENTRY_POINT = FailSafeDxeEntryPoint >> + >> +[Sources] >> + FailSafe.h >> + FailSafeDxe.c >> + Watchdog.c >> + Watchdog.h >> + >> +[Packages] >> + ArmPkg/ArmPkg.dec >> + ArmPlatformPkg/ArmPlatformPkg.dec >> + EmbeddedPkg/EmbeddedPkg.dec >> + MdeModulePkg/MdeModulePkg.dec >> + MdePkg/MdePkg.dec >> + Platform/Ampere/AmperePlatformPkg/AmperePlatformPkg.dec >> + Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec >> + Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec >> + >> +[LibraryClasses] >> + ArmSmcLib >> + DebugLib >> + FailSafeLib >> + NVParamLib >> + PcdLib >> + TimerLib >> + UefiBootServicesTableLib >> + UefiDriverEntryPoint >> + UefiLib >> + UefiRuntimeServicesTableLib >> + >> +[Pcd] >> + gArmTokenSpaceGuid.PcdGenericWatchdogControlBase >> + gArmTokenSpaceGuid.PcdGenericWatchdogEl2IntrNum >> + >> +[Protocols] >> + gEfiWatchdogTimerArchProtocolGuid ## PRODUCES >> + gHardwareInterrupt2ProtocolGuid ## CONSUMES >> + >> +[Depex] >> + gHardwareInterrupt2ProtocolGuid >> diff --git a/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafe.h b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafe.h >> new file mode 100644 >> index 000000000000..8bf3a98f1d8e >> --- /dev/null >> +++ b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafe.h >> @@ -0,0 +1,20 @@ >> +/** @file >> + >> + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.
>> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> + >> +**/ >> + >> +#ifndef FAILSAFE_H_ >> +#define FAILSAFE_H_ >> + >> +#include >> + >> +BOOLEAN >> +EFIAPI >> +IsFailSafeOff ( >> + VOID >> + ); >> + >> +#endif /* FAILSAFE_H_ */ >> diff --git a/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/Watchdog.h b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/Watchdog.h >> new file mode 100755 >> index 000000000000..6c9106fdbea5 >> --- /dev/null >> +++ b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/Watchdog.h >> @@ -0,0 +1,29 @@ >> +/** @file >> + >> + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.
>> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> + >> +**/ >> + >> +#ifndef GENERIC_WATCHDOG_H_ >> +#define GENERIC_WATCHDOG_H_ >> + >> +#include >> + >> +/* The number of 100ns periods (the unit of time passed to these functions) >> + in a second */ >> +#define TIME_UNITS_PER_SECOND 10000000 >> + >> +/** >> + The function to install Watchdog timer protocol to the system >> + >> + @retval Return EFI_SUCCESS if install Watchdog timer protocol successfully. >> + **/ >> +EFI_STATUS >> +EFIAPI >> +WatchdogTimerInstallProtocol ( >> + EFI_WATCHDOG_TIMER_ARCH_PROTOCOL **WatchdogTimerProtocol >> + ); >> + >> +#endif /* GENERIC_WATCHDOG_H_ */ >> diff --git a/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.c b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.c >> new file mode 100644 >> index 000000000000..1b8978b12ea7 >> --- /dev/null >> +++ b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.c >> @@ -0,0 +1,184 @@ >> +/** @file >> + >> + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.
>> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> + >> +**/ >> + >> +#include >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include "FailSafe.h" >> +#include "Watchdog.h" >> + >> +STATIC UINTN gWatchdogOSTimeout; >> +STATIC BOOLEAN gFailSafeOff; >> +STATIC EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *gWatchdogTimer; >> + >> +EFI_STATUS >> +EFIAPI >> +FailSafeTestBootFailure ( >> + VOID >> + ); >> + >> +STATIC VOID >> +FailSafeTurnOff ( >> + VOID >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + if (IsFailSafeOff ()) { >> + return; >> + } >> + >> + Status = FailSafeBootSuccessfully (); >> + ASSERT_EFI_ERROR (Status); >> + >> + gFailSafeOff = TRUE; >> + >> + /* Disable Watchdog timer */ >> + gWatchdogTimer->SetTimerPeriod (gWatchdogTimer, 0); >> +} >> + >> +BOOLEAN >> +EFIAPI >> +IsFailSafeOff ( >> + VOID >> + ) >> +{ >> + return gFailSafeOff; >> +} >> + >> +/** >> + The function to disable Watchdog timer when enter Setup screen >> + **/ >> +VOID >> +WdtTimerEnterSetupScreenCallback ( >> + IN EFI_EVENT Event, >> + IN VOID *Context >> + ) >> +{ >> + /* Make sure FailSafe is turned off */ >> + FailSafeTurnOff (); >> +} >> + >> +/** >> + The function to refresh Watchdog timer in the event before booting >> + **/ >> +VOID >> +WdtTimerBeforeBootCallback ( >> + IN EFI_EVENT Event, >> + IN VOID *Context >> + ) >> +{ >> + /* >> + * At this point, the system is considered boot successfully to BIOS >> + */ >> + FailSafeTurnOff (); >> + >> + /* >> + * It is BIOS's responsibility to setup Watchdog when load an EFI application >> + * after this step >> + */ >> +} >> + >> +/** >> + The function to refresh Watchdog timer in the event before exiting boot services >> + **/ >> +VOID >> +WdtTimerExitBootServiceCallback ( >> + IN EFI_EVENT Event, >> + IN VOID *Context >> + ) >> +{ >> + >> + /* Enable Watchdog timer for OS booting */ >> + if (gWatchdogOSTimeout != 0) { >> + gWatchdogTimer->SetTimerPeriod ( >> + gWatchdogTimer, >> + gWatchdogOSTimeout * TIME_UNITS_PER_SECOND >> + ); >> + } else { >> + /* Disable Watchdog timer */ >> + gWatchdogTimer->SetTimerPeriod (gWatchdogTimer, 0); >> + } >> +} >> + >> +/** >> + This function is a hook called when user loads the manufacturing >> + or optimal defaults. >> + >> + @param Defaults : (NVRAM_VARIABLE *)optimal or manufacturing >> + @Data : Messagebox >> + >> + @retval VOID >> +**/ >> +VOID >> +LoadNVRAMDefaultConfig ( >> + IN VOID *Defaults, >> + IN UINTN Data >> + ) >> +{ >> + NVParamClrAll (); >> +} >> + >> +/** >> + Main entry for this driver. >> + >> + @param ImageHandle Image handle this driver. >> + @param SystemTable Pointer to SystemTable. >> + >> + @retval EFI_SUCESS This function always complete successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +FailSafeDxeEntryPoint ( >> + IN EFI_HANDLE ImageHandle, >> + IN EFI_SYSTEM_TABLE *SystemTable >> + ) >> +{ >> + EFI_EVENT ExitBootServicesEvent; >> + EFI_STATUS Status; >> + >> + gFailSafeOff = FALSE; >> + >> + FailSafeTestBootFailure (); >> + >> + /* We need to setup non secure Watchdog to ensure that the system will >> + * boot to OS successfully. >> + * >> + * The BIOS doesn't handle Watchdog interrupt so we expect WS1 asserted EL3 >> + * when Watchdog timeout triggered >> + */ >> + >> + Status = WatchdogTimerInstallProtocol (&gWatchdogTimer); >> + ASSERT_EFI_ERROR (Status); >> + >> + // FIXME: We should register a callback function before entering to Setup screen >> + // rather than always call it at DXE phase. >> + FailSafeTurnOff (); >> + >> + /* Register event before exit boot services */ >> + Status = gBS->CreateEvent ( >> + EVT_SIGNAL_EXIT_BOOT_SERVICES, >> + TPL_NOTIFY, >> + WdtTimerExitBootServiceCallback, >> + NULL, >> + &ExitBootServicesEvent >> + ); >> + ASSERT_EFI_ERROR (Status); >> + >> + return Status; >> +} >> diff --git a/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/Watchdog.c b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/Watchdog.c >> new file mode 100644 >> index 000000000000..34329d04206a >> --- /dev/null >> +++ b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/Watchdog.c >> @@ -0,0 +1,357 @@ >> +/** @file >> + >> + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.
>> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> + >> +**/ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include "FailSafe.h" >> +#include "Watchdog.h" >> + >> +/* Watchdog timer controller registers */ >> +#define WDT_CTRL_BASE_REG FixedPcdGet64 (PcdGenericWatchdogControlBase) >> +#define WDT_CTRL_WCS_OFF 0x0 >> +#define WDT_CTRL_WCS_ENABLE_MASK 0x1 >> +#define WDT_CTRL_WOR_OFF 0x8 >> +#define WDT_CTRL_WCV_OFF 0x10 >> +#define WS0_INTERRUPT_SOURCE FixedPcdGet32 (PcdGenericWatchdogEl2IntrNum) >> + >> +STATIC UINT64 mNumTimerTicks; >> +STATIC EFI_HARDWARE_INTERRUPT2_PROTOCOL *mInterruptProtocol; >> +BOOLEAN mInterruptWS0Enabled; >> + >> +STATIC >> +VOID >> +WatchdogTimerWriteOffsetRegister ( >> + UINT32 Value >> + ) >> +{ >> + MmioWrite32 (WDT_CTRL_BASE_REG + WDT_CTRL_WOR_OFF, Value); >> +} >> + >> +STATIC >> +VOID >> +WatchdogTimerWriteCompareRegister ( >> + UINT64 Value >> + ) >> +{ >> + MmioWrite64 (WDT_CTRL_BASE_REG + WDT_CTRL_WCV_OFF, Value); >> +} >> + >> +STATIC >> +EFI_STATUS >> +WatchdogTimerEnable ( >> + IN BOOLEAN Enable >> + ) >> +{ >> + UINT32 Val = MmioRead32 ((UINTN)(WDT_CTRL_BASE_REG + WDT_CTRL_WCS_OFF)); >> + >> + if (Enable) { >> + Val |= WDT_CTRL_WCS_ENABLE_MASK; >> + } else { >> + Val &= ~WDT_CTRL_WCS_ENABLE_MASK; >> + } >> + MmioWrite32 ((UINTN)(WDT_CTRL_BASE_REG + WDT_CTRL_WCS_OFF), Val); >> + >> + return EFI_SUCCESS; >> +} >> + >> +STATIC >> +EFI_STATUS >> +WatchdogTimerSetup ( >> + VOID >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + /* Disable Watchdog timer */ >> + WatchdogTimerEnable (FALSE); >> + >> + if (!mInterruptWS0Enabled) { >> + Status = mInterruptProtocol->EnableInterruptSource ( >> + mInterruptProtocol, >> + WS0_INTERRUPT_SOURCE >> + ); >> + ASSERT_EFI_ERROR (Status); >> + >> + mInterruptWS0Enabled = TRUE; >> + } >> + >> + if (mNumTimerTicks == 0) { >> + return EFI_SUCCESS; >> + } >> + >> + /* If the number of required ticks is greater than the max the Watchdog's >> + offset register (WOR) can hold, we need to manually compute and set >> + the compare register (WCV) */ >> + if (mNumTimerTicks > MAX_UINT32) { >> + /* We need to enable the Watchdog *before* writing to the compare register, >> + because enabling the Watchdog causes an "explicit refresh", which >> + clobbers the compare register (WCV). In order to make sure this doesn't >> + trigger an interrupt, set the offset to max. */ >> + WatchdogTimerWriteOffsetRegister (MAX_UINT32); >> + WatchdogTimerEnable (TRUE); >> + WatchdogTimerWriteCompareRegister (ArmGenericTimerGetSystemCount () + mNumTimerTicks); >> + } else { >> + WatchdogTimerWriteOffsetRegister ((UINT32)mNumTimerTicks); >> + WatchdogTimerEnable (TRUE); >> + } >> + >> + return EFI_SUCCESS; >> +} >> + >> + >> +/* This function is called when the Watchdog's first signal (WS0) goes high. >> + It uses the ResetSystem Runtime Service to reset the board. >> +*/ >> +VOID >> +EFIAPI >> +WatchdogTimerInterruptHandler ( >> + IN HARDWARE_INTERRUPT_SOURCE Source, >> + IN EFI_SYSTEM_CONTEXT SystemContext >> + ) >> +{ >> + STATIC CONST CHAR16 ResetString[]= L"The generic Watchdog timer ran out."; >> + >> + mInterruptProtocol->EndOfInterrupt (mInterruptProtocol, Source); >> + >> + if (!IsFailSafeOff ()) { >> + /* Not handling interrupt as ATF is monitoring it */ >> + return; >> + } >> + >> + WatchdogTimerEnable (FALSE); >> + >> + gRT->ResetSystem ( >> + EfiResetCold, >> + EFI_TIMEOUT, >> + StrSize (ResetString), >> + (VOID *)&ResetString >> + ); >> + >> + /* If we got here then the reset didn't work */ >> + ASSERT (FALSE); >> +} >> + >> +/** >> + This function registers the handler NotifyFunction so it is called every time >> + the Watchdog timer expires. It also passes the amount of time since the last >> + handler call to the NotifyFunction. >> + If NotifyFunction is not NULL and a handler is not already registered, >> + then the new handler is registered and EFI_SUCCESS is returned. >> + If NotifyFunction is NULL, and a handler is already registered, >> + then that handler is unregistered. >> + If an attempt is made to register a handler when a handler is already >> + registered, then EFI_ALREADY_STARTED is returned. >> + If an attempt is made to unregister a handler when a handler is not >> + registered, then EFI_INVALID_PARAMETER is returned. >> + >> + @param This The EFI_TIMER_ARCH_PROTOCOL instance. >> + @param NotifyFunction The function to call when a timer interrupt fires. >> + This function executes at TPL_HIGH_LEVEL. The DXE >> + Core will register a handler for the timer interrupt, >> + so it can know how much time has passed. This >> + information is used to signal timer based events. >> + NULL will unregister the handler. >> + >> + @retval EFI_UNSUPPORTED The code does not support NotifyFunction. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +WatchdogTimerRegisterHandler ( >> + IN CONST EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, >> + IN EFI_WATCHDOG_TIMER_NOTIFY NotifyFunction >> + ) >> +{ >> + /* Not support. Watchdog will reset the board */ >> + return EFI_UNSUPPORTED; >> +} >> + >> +/** >> + This function sets the amount of time to wait before firing the Watchdog >> + timer to TimerPeriod 100ns units. If TimerPeriod is 0, then the Watchdog >> + timer is disabled. >> + >> + @param This The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance. >> + @param TimerPeriod The amount of time in 100ns units to wait before >> + the Watchdog timer is fired. If TimerPeriod is zero, >> + then the Watchdog timer is disabled. >> + >> + @retval EFI_SUCCESS The Watchdog timer has been programmed to fire >> + in Time 100ns units. >> + @retval EFI_DEVICE_ERROR A Watchdog timer could not be programmed due >> + to a device error. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +WatchdogTimerSetPeriod ( >> + IN CONST EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, >> + IN UINT64 TimerPeriod // In 100ns units >> + ) >> +{ >> + mNumTimerTicks = (ArmGenericTimerGetTimerFreq () * TimerPeriod) / TIME_UNITS_PER_SECOND; >> + >> + if (!IsFailSafeOff ()) { >> + /* Not support Watchdog timer service until FailSafe is off as ATF is monitoring it */ >> + return EFI_SUCCESS; >> + } >> + >> + return WatchdogTimerSetup (); >> +} >> + >> +/** >> + This function retrieves the period of timer interrupts in 100ns units, >> + returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod >> + is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is >> + returned, then the timer is currently disabled. >> + >> + @param This The EFI_TIMER_ARCH_PROTOCOL instance. >> + @param TimerPeriod A pointer to the timer period to retrieve in >> + 100ns units. If 0 is returned, then the timer is >> + currently disabled. >> + >> + >> + @retval EFI_SUCCESS The timer period was returned in TimerPeriod. >> + @retval EFI_INVALID_PARAMETER TimerPeriod is NULL. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +WatchdogTimerGetPeriod ( >> + IN CONST EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, >> + OUT UINT64 *TimerPeriod >> + ) >> +{ >> + if (TimerPeriod == NULL) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + *TimerPeriod = ((TIME_UNITS_PER_SECOND / ArmGenericTimerGetTimerFreq ()) * mNumTimerTicks); >> + >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + Interface structure for the Watchdog Architectural Protocol. >> + >> + @par Protocol Description: >> + This protocol provides a service to set the amount of time to wait >> + before firing the Watchdog timer, and it also provides a service to >> + register a handler that is invoked when the Watchdog timer fires. >> + >> + @par When the Watchdog timer fires, control will be passed to a handler >> + if one has been registered. If no handler has been registered, >> + or the registered handler returns, then the system will be >> + reset by calling the Runtime Service ResetSystem(). >> + >> + @param RegisterHandler >> + Registers a handler that will be called each time the >> + Watchdogtimer interrupt fires. TimerPeriod defines the minimum >> + time between timer interrupts, so TimerPeriod will also >> + be the minimum time between calls to the registered >> + handler. >> + NOTE: If the Watchdog resets the system in hardware, then >> + this function will not have any chance of executing. >> + >> + @param SetTimerPeriod >> + Sets the period of the timer interrupt in 100ns units. >> + This function is optional, and may return EFI_UNSUPPORTED. >> + If this function is supported, then the timer period will >> + be rounded up to the nearest supported timer period. >> + >> + @param GetTimerPeriod >> + Retrieves the period of the timer interrupt in 100ns units. >> + >> +**/ >> +STATIC EFI_WATCHDOG_TIMER_ARCH_PROTOCOL gWatchdogTimer = { >> + (EFI_WATCHDOG_TIMER_REGISTER_HANDLER)WatchdogTimerRegisterHandler, >> + (EFI_WATCHDOG_TIMER_SET_TIMER_PERIOD)WatchdogTimerSetPeriod, >> + (EFI_WATCHDOG_TIMER_GET_TIMER_PERIOD)WatchdogTimerGetPeriod >> +}; >> + >> +EFI_STATUS >> +EFIAPI >> +WatchdogTimerInstallProtocol ( >> + EFI_WATCHDOG_TIMER_ARCH_PROTOCOL **WatchdogTimerProtocol >> + ) >> +{ >> + EFI_STATUS Status; >> + EFI_HANDLE Handle; >> + EFI_TPL CurrentTpl; >> + >> + /* Make sure the Watchdog Timer Architectural Protocol has not been installed >> + in the system yet. >> + This will avoid conflicts with the universal Watchdog */ >> + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiWatchdogTimerArchProtocolGuid); >> + >> + ASSERT (ArmGenericTimerGetTimerFreq () != 0); >> + >> + /* Install interrupt handler */ >> + Status = gBS->LocateProtocol ( >> + &gHardwareInterrupt2ProtocolGuid, >> + NULL, >> + (VOID **)&mInterruptProtocol >> + ); >> + ASSERT_EFI_ERROR (Status); >> + >> + /* >> + * We don't want to be interrupted while registering Watchdog interrupt source as the interrupt >> + * may be trigger in the middle because the interrupt line already enabled in the EL3. >> + */ >> + CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); >> + >> + Status = mInterruptProtocol->RegisterInterruptSource ( >> + mInterruptProtocol, >> + WS0_INTERRUPT_SOURCE, >> + WatchdogTimerInterruptHandler >> + ); >> + ASSERT_EFI_ERROR (Status); >> + >> + /* Don't enable interrupt until FailSafe off */ >> + mInterruptWS0Enabled = FALSE; >> + Status = mInterruptProtocol->DisableInterruptSource ( >> + mInterruptProtocol, >> + WS0_INTERRUPT_SOURCE >> + ); >> + ASSERT_EFI_ERROR (Status); >> + >> + gBS->RestoreTPL (CurrentTpl); >> + >> + Status = mInterruptProtocol->SetTriggerType ( >> + mInterruptProtocol, >> + WS0_INTERRUPT_SOURCE, >> + EFI_HARDWARE_INTERRUPT2_TRIGGER_LEVEL_HIGH >> + ); >> + ASSERT_EFI_ERROR (Status); >> + >> + /* Install the Timer Architectural Protocol onto a new handle */ >> + Handle = NULL; >> + Status = gBS->InstallMultipleProtocolInterfaces ( >> + &Handle, >> + &gEfiWatchdogTimerArchProtocolGuid, >> + &gWatchdogTimer, >> + NULL >> + ); >> + ASSERT_EFI_ERROR (Status); >> + >> + mNumTimerTicks = 0; >> + >> + if (WatchdogTimerProtocol != NULL) { >> + *WatchdogTimerProtocol = &gWatchdogTimer; >> + } >> + >> + return Status; >> +} >> -- >> 2.17.1 >>