security/tcg/opal_s3: hook into default SMI/resume paths

Provide common entry points for the OPAL S3 unlock feature and wire them
into the generic x86 SMM and S3 resume code.

- Add opal_s3_smi_{apmc,sleep,sleep_finalize} helpers.
- Call these helpers from the default weak mainboard SMI hooks when
  CONFIG(TCG_OPAL_S3_UNLOCK) is enabled. This keeps the feature usable
  without forcing boards to implement new SMI handlers.
- Trigger the SMM unlock on S3 resume from arch/x86/acpi_s3.c.

Select SMM_OPAL_S3_STATE_SMRAM so the secret is persisted across SMM
handler reload. Add a delay and retry loop before unlock, and restore
NVMe BAR0 if the device loses PCI config state across S3.

The SMM side continues to whitelist only the OPAL service and unlock
APMC commands and fails closed if any invariant is violated.

TEST=tested with rest of patch train

Change-Id: I86a44760a189219a95914bd3549997880fb0242b
Signed-off-by: Sean Rhodes <sean@starlabs.systems>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/91045
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Sean Rhodes 2026-02-01 21:46:56 +00:00 committed by Matt DeVillier
commit 468f8131ec
7 changed files with 527 additions and 0 deletions

View file

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SECURITY_TCG_OPAL_S3_RESUME_H
#define SECURITY_TCG_OPAL_S3_RESUME_H
/*
* Trigger an SMM-assisted OPAL unlock during S3 resume.
*
* The unlock implementation lives in SMM; this is a small ramstage helper
* that issues the APMC trigger. It is called automatically from the x86
* resume path when enabled.
*/
void opal_s3_resume_unlock(void);
#endif

View file

@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SECURITY_TCG_OPAL_S3_SMM_H
#define SECURITY_TCG_OPAL_S3_SMM_H
#include <types.h>
/*
* OPAL S3 SMM helpers.
*
* These helpers are called from SMI handlers. When the feature is disabled,
* these APIs compile to no-ops so callers do not need preprocessor guards.
*/
#if CONFIG(TCG_OPAL_S3_UNLOCK)
int opal_s3_smi_apmc(u8 apmc);
void opal_s3_smi_sleep(u8 slp_typ);
void opal_s3_smi_sleep_finalize(u8 slp_typ);
#else
static inline int opal_s3_smi_apmc(u8 apmc)
{
(void)apmc;
return 0;
}
static inline void opal_s3_smi_sleep(u8 slp_typ)
{
(void)slp_typ;
}
static inline void opal_s3_smi_sleep_finalize(u8 slp_typ)
{
(void)slp_typ;
}
#endif
#endif