KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/powerpc/ieee1275/ieee1275.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/powerpc/ieee1275/platform_keystore.h
endif
if COND_sparc64_ieee1275
powerpc_ieee1275 = kern/powerpc/dl.c;
powerpc_ieee1275 = kern/powerpc/compiler-rt.S;
powerpc_ieee1275 = kern/lockdown.c;
+ powerpc_ieee1275 = kern/powerpc/ieee1275/ieee1275.c;
+ powerpc_ieee1275 = kern/powerpc/ieee1275/platform_keystore.c;
sparc64_ieee1275 = kern/sparc64/cache.S;
sparc64_ieee1275 = kern/sparc64/dl.c;
#define IEEE1275_PHANDLE_INVALID ((grub_ieee1275_cell_t) -1)
#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_cell_t) 0)
-#define IEEE1275_CELL_INVALID ((grub_ieee1275_cell_t) -1)
\f
#endif
#if defined(__powerpc__)
#include <grub/lockdown.h>
+#include <grub/powerpc/ieee1275/ieee1275.h>
+#include <grub/powerpc/ieee1275/platform_keystore.h>
#endif
#ifdef __powerpc__
}
else
grub_dprintf ("ieee1275", "Secure Boot Disabled\n");
+
+ grub_pks_keystore_init ();
}
#endif /* __powerpc__ */
grub_addr_t grub_modbase;
--- /dev/null
+/* ieee1275.c - Access the Open Firmware client interface. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
+ * Copyright (C) 2020, 2021, 2022, 2023, 2024, 2025 IBM Corporation
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <grub/ieee1275/ieee1275.h>
+#include <grub/powerpc/ieee1275/ieee1275.h>
+#include <grub/misc.h>
+
+grub_int32_t
+grub_ieee1275_test (const char *interface_name)
+{
+ struct test_args
+ {
+ struct grub_ieee1275_common_hdr common;/* The header information like interface name, number of inputs and outputs. */
+ grub_ieee1275_cell_t name; /* The interface name. */
+ grub_ieee1275_cell_t missing;
+ } args;
+
+ INIT_IEEE1275_COMMON (&args.common, "test", 1, 1);
+ args.name = (grub_ieee1275_cell_t) interface_name;
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return -1;
+
+ if (args.missing == IEEE1275_CELL_INVALID)
+ return -1;
+
+ return 0;
+}
+
+grub_int32_t
+grub_ieee1275_pks_max_object_size (grub_uint32_t *result)
+{
+ struct mos_args
+ {
+ struct grub_ieee1275_common_hdr common;/* The header information like interface name, number of inputs and outputs. */
+ grub_ieee1275_cell_t size; /* The maximum object size for a PKS object. */
+ } args;
+
+ INIT_IEEE1275_COMMON (&args.common, GRUB_PKS_MAX_OBJ_INTERFACE, 0, 1);
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return -1;
+
+ if (args.size == IEEE1275_CELL_INVALID || args.size == 0)
+ return -1;
+
+ *result = args.size;
+
+ return 0;
+}
+
+grub_int32_t
+grub_ieee1275_pks_read_object (const grub_uint32_t consumer, const char *label,
+ const grub_uint32_t label_len, const grub_uint32_t buffer_len,
+ grub_uint8_t *buffer, grub_uint32_t *data_len,
+ grub_uint32_t *policies)
+{
+ struct pks_read_args
+ {
+ struct grub_ieee1275_common_hdr common; /* The header information like interface name, number of inputs and outputs. */
+ grub_ieee1275_cell_t consumer; /* The object belonging to consumer with the label. */
+ grub_ieee1275_cell_t label; /* Object label buffer logical real address. */
+ grub_ieee1275_cell_t label_len; /* The byte length of the object label. */
+ grub_ieee1275_cell_t buffer; /* Output buffer logical real address. */
+ grub_ieee1275_cell_t buffer_len; /* Length of the output buffer. */
+ grub_ieee1275_cell_t data_len; /* The number of bytes copied to the output buffer. */
+ grub_ieee1275_cell_t policies; /* The object policies. */
+ grub_int32_t rc; /* The return code. */
+ } args;
+
+ INIT_IEEE1275_COMMON (&args.common, GRUB_PKS_READ_OBJ_INTERFACE, 5, 3);
+ args.consumer = consumer;
+ args.label_len = label_len;
+ args.buffer_len = buffer_len;
+ args.label = (grub_ieee1275_cell_t) label;
+ args.buffer = (grub_ieee1275_cell_t) buffer;
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return -1;
+
+ if (args.data_len == IEEE1275_CELL_INVALID)
+ return -1;
+
+ *data_len = args.data_len;
+ *policies = args.policies;
+
+ return args.rc;
+}
+
+grub_int32_t
+grub_ieee1275_pks_read_sbvar (const grub_uint32_t sbvar_flags, const grub_uint32_t sbvar_type,
+ const grub_uint32_t buffer_len, grub_uint8_t *buffer,
+ grub_size_t *data_len)
+{
+ struct pks_read_sbvar_args
+ {
+ struct grub_ieee1275_common_hdr common; /* The header information like interface name, number of inputs and outputs. */
+ grub_ieee1275_cell_t sbvar_flags; /* The sbvar operation flags. */
+ grub_ieee1275_cell_t sbvar_type; /* The sbvar being requested. */
+ grub_ieee1275_cell_t buffer; /* Output buffer logical real address. */
+ grub_ieee1275_cell_t buffer_len; /* Length of the Output buffer. */
+ grub_ieee1275_cell_t data_len; /* The number of bytes copied to the output buffer. */
+ grub_int32_t rc; /* The return code. */
+ } args;
+
+ INIT_IEEE1275_COMMON (&args.common, GRUB_PKS_READ_SBVAR_INTERFACE, 4, 2);
+ args.sbvar_flags = sbvar_flags;
+ args.sbvar_type = sbvar_type;
+ args.buffer_len = buffer_len;
+ args.buffer = (grub_ieee1275_cell_t) buffer;
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return -1;
+
+ if (args.data_len == IEEE1275_CELL_INVALID)
+ return -1;
+
+ *data_len = args.data_len;
+
+ return args.rc;
+}
--- /dev/null
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2024 Free Software Foundation, Inc.
+ * Copyright (C) 2022, 2023, 2024, 2025 IBM Corporation
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/mm.h>
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/lockdown.h>
+#include <grub/ieee1275/ieee1275.h>
+#include <grub/powerpc/ieee1275/ieee1275.h>
+#include <grub/powerpc/ieee1275/platform_keystore.h>
+
+/* PKS object maximum size. */
+static grub_uint32_t pks_max_object_size = 0;
+
+/* Platform KeyStore db and dbx. */
+static grub_pks_t pks_keystore = { .db = NULL, .dbx = NULL, .db_entries = 0,
+ .dbx_entries = 0, .db_exists = true};
+/*
+ * pks_use_keystore: Key Management Modes
+ * False: Static key management (use built-in Keys). This is default.
+ * True: Dynamic key management (use Platform KeySotre).
+ */
+static bool pks_use_keystore = false;
+
+/*
+ * Reads the Globally Unique Identifier (GUID), EFI Signature Database (ESD),
+ * and its size from the Platform KeyStore EFI Signature List (ESL), then
+ * stores them into the PKS Signature Database (SD) (i.e., pks_sd buffer
+ * and pks_sd entries) in the GRUB.
+ */
+static grub_err_t
+_esl_to_esd (const grub_uint8_t *esl_data, grub_size_t esl_size,
+ const grub_size_t signature_size, const grub_packed_guid_t *guid,
+ grub_pks_sd_t **pks_sd, grub_uint32_t *pks_sd_entries)
+{
+ grub_esd_t *esd;
+ grub_pks_sd_t *signature = *pks_sd;
+ grub_uint32_t entries = *pks_sd_entries;
+ grub_size_t data_size, offset = 0;
+
+ /* Reads the ESD from ESL. */
+ while (esl_size > 0)
+ {
+ esd = (grub_esd_t *) (esl_data + offset);
+ data_size = signature_size - sizeof (grub_esd_t);
+
+ signature = grub_realloc (signature, (entries + 1) * sizeof (grub_pks_sd_t));
+ if (signature == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+
+ signature[entries].data = grub_malloc (data_size * sizeof (grub_uint8_t));
+ if (signature[entries].data == NULL)
+ {
+ /* Allocated memory will be freed by grub_pks_free_data(). */
+ *pks_sd = signature;
+ *pks_sd_entries = entries + 1;
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+ }
+
+ grub_memcpy (signature[entries].data, esd->signature_data, data_size);
+ signature[entries].data_size = data_size;
+ signature[entries].guid = *guid;
+ entries++;
+ esl_size -= signature_size;
+ offset += signature_size;
+ }
+
+ *pks_sd = signature;
+ *pks_sd_entries = entries;
+
+ return GRUB_ERR_NONE;
+}
+
+/* Extract the ESD after removing the ESL header from ESL. */
+static grub_err_t
+esl_to_esd (const grub_uint8_t *esl_data, grub_size_t *next_esl,
+ grub_pks_sd_t **pks_sd, grub_uint32_t *pks_sd_entries)
+{
+ grub_packed_guid_t guid;
+ grub_esl_t *esl;
+ grub_size_t offset, esl_size, signature_size, signature_header_size;
+
+ /* Convert the ESL data into the ESL. */
+ esl = (grub_esl_t *) esl_data;
+ if (*next_esl < sizeof (grub_esl_t) || esl == NULL)
+ return grub_error (GRUB_ERR_BUG, "invalid ESL");
+
+ esl_size = grub_le_to_cpu32 (esl->signature_list_size);
+ signature_header_size = grub_le_to_cpu32 (esl->signature_header_size);
+ signature_size = grub_le_to_cpu32 (esl->signature_size);
+ grub_memcpy (&guid, &esl->signature_type, sizeof (grub_packed_guid_t));
+
+ if (esl_size < sizeof (grub_esl_t) || esl_size > *next_esl)
+ return grub_error (GRUB_ERR_BUG, "invalid ESL size (%u)\n", esl_size);
+
+ *next_esl = esl_size;
+ offset = sizeof (grub_esl_t) + signature_header_size;
+ esl_size = esl_size - offset;
+
+ return _esl_to_esd (esl_data + offset, esl_size, signature_size, &guid,
+ pks_sd, pks_sd_entries);
+}
+
+/*
+ * Import the EFI Signature Database (ESD) and the number of ESD from the ESL
+ * into the pks_sd buffer and pks_sd entries.
+ */
+static grub_err_t
+pks_sd_from_esl (const grub_uint8_t *esl_data, grub_size_t esl_size,
+ grub_pks_sd_t **pks_sd, grub_uint32_t *pks_sd_entries)
+{
+ grub_err_t rc;
+ grub_size_t next_esl = esl_size;
+
+ do
+ {
+ rc = esl_to_esd (esl_data, &next_esl, pks_sd, pks_sd_entries);
+ if (rc != GRUB_ERR_NONE)
+ break;
+
+ esl_data += next_esl;
+ esl_size -= next_esl;
+ next_esl = esl_size;
+ }
+ while (esl_size > 0);
+
+ return rc;
+}
+
+/* Read the secure boot version from PKS as an object. Caller must free result. */
+static grub_err_t
+read_sbversion_from_pks (grub_uint8_t **out)
+{
+ grub_int32_t rc;
+ grub_uint32_t outlen = 0, policy = 0;
+
+ *out = grub_malloc (pks_max_object_size);
+ if (*out == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+
+ rc = grub_ieee1275_pks_read_object (GRUB_PKS_CONSUMER_FW, GRUB_SB_VERSION_KEY_NAME,
+ GRUB_SB_VERSION_KEY_LEN, pks_max_object_size, *out,
+ &outlen, &policy);
+ if (rc < 0)
+ {
+ grub_free (*out);
+ return grub_error (GRUB_ERR_READ_ERROR, "SB version read failed (%d)\n", rc);
+ }
+
+ if (outlen != 1 || (**out >= 2))
+ {
+ grub_free (*out);
+ return grub_error (GRUB_ERR_BAD_NUMBER, "found unexpected SB version: %u\n", **out);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * Reads the secure boot variable from PKS, unpacks it, read the ESD from ESL,
+ * and store the information in the pks_sd buffer.
+ */
+static grub_err_t
+read_sbvar_from_pks (const grub_uint32_t sbvarflags, const grub_uint32_t sbvartype,
+ grub_pks_sd_t **pks_sd, grub_uint32_t *pks_sd_entries)
+{
+ grub_int32_t rc;
+ grub_err_t err = GRUB_ERR_NONE;
+ grub_uint8_t *esl_data = NULL;
+ grub_size_t esl_data_size = 0;
+
+ esl_data = grub_malloc (pks_max_object_size);
+ if (esl_data == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+
+ rc = grub_ieee1275_pks_read_sbvar (sbvarflags, sbvartype, pks_max_object_size,
+ esl_data, &esl_data_size);
+ if (rc == IEEE1275_CELL_NOT_FOUND)
+ {
+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "secure boot variable %s not found (%d)",
+ (sbvartype == GRUB_PKS_SBVAR_DB) ? "db" : "dbx", rc);
+ goto fail;
+ }
+ else if (rc < 0)
+ {
+ err = grub_error (GRUB_ERR_READ_ERROR, "secure boot variable %s reading (%d)",
+ (sbvartype == GRUB_PKS_SBVAR_DB) ? "db" : "dbx", rc);
+ goto fail;
+ }
+
+ if (esl_data_size > 0)
+ err = pks_sd_from_esl (esl_data, esl_data_size, pks_sd, pks_sd_entries);
+ else
+ err = GRUB_ERR_BAD_NUMBER;
+
+ fail:
+ grub_free (esl_data);
+
+ return err;
+}
+
+/*
+ * Test the availability of PKS support. If PKS support is avaialble and objects
+ * present, it reads the secure boot version (SB_VERSION) from PKS.
+ *
+ * SB_VERSION: Key Management Mode
+ * 1 - Enable dynamic key management mode. Read the db and dbx variables from PKS,
+ * and use them for signature verification.
+ * 0 - Enable static key management mode. Read keys from the GRUB ELF Note and use
+ * it for signature verification.
+ */
+static bool
+is_pks_present (void)
+{
+ grub_err_t err;
+ grub_int32_t rc;
+ grub_uint8_t *data = NULL;
+ bool ret = false;
+
+ rc = grub_ieee1275_test (GRUB_PKS_MAX_OBJ_INTERFACE);
+ if (rc < 0)
+ {
+ grub_error (GRUB_ERR_BAD_FIRMWARE, "firmware doesn't have PKS support\n");
+ return ret;
+ }
+ else
+ {
+ rc = grub_ieee1275_pks_max_object_size (&pks_max_object_size);
+ if (rc < 0)
+ {
+ grub_error (GRUB_ERR_BAD_NUMBER, "PKS support is there but it has zero objects\n");
+ return ret;
+ }
+ }
+
+ err = read_sbversion_from_pks (&data);
+ if (err != GRUB_ERR_NONE)
+ return ret;
+
+ /*
+ * If *data == 1, use dynamic key management and read the keys from the PKS.
+ * Else, use static key management and read the keys from the GRUB ELF Note.
+ */
+ ret = ((*data == 1) ? true : false);
+
+ grub_free (data);
+
+ return ret;
+}
+
+/* Free allocated memory. */
+void
+grub_pks_free_data (void)
+{
+ grub_size_t i;
+
+ for (i = 0; i < pks_keystore.db_entries; i++)
+ grub_free (pks_keystore.db[i].data);
+
+ for (i = 0; i < pks_keystore.dbx_entries; i++)
+ grub_free (pks_keystore.dbx[i].data);
+
+ grub_free (pks_keystore.db);
+ grub_free (pks_keystore.dbx);
+ grub_memset (&pks_keystore, 0, sizeof (grub_pks_t));
+}
+
+grub_pks_t *
+grub_pks_get_keystore (void)
+{
+ return (pks_use_keystore == true) ? &pks_keystore : NULL;
+}
+
+/* Initialization of the Platform KeyStore. */
+void
+grub_pks_keystore_init (void)
+{
+ grub_err_t rc_db, rc_dbx;
+
+ grub_dprintf ("ieee1275", "trying to load Platform KeyStore\n");
+
+ if (is_pks_present () == false)
+ {
+ grub_dprintf ("ieee1275", "Platform PKS is not available\n");
+ return;
+ }
+
+ /*
+ * When read db from PKS, there are three scenarios
+ * 1. db fully loaded from PKS
+ * 2. db partially loaded from PKS
+ * 3. no keys are loaded from db (if db does not exist in PKS), default to
+ * built-in keys (static keys)
+ * each of these scenarios, the db keys are checked against dbx.
+ */
+ rc_db = read_sbvar_from_pks (0, GRUB_PKS_SBVAR_DB, &pks_keystore.db, &pks_keystore.db_entries);
+ if (rc_db == GRUB_ERR_FILE_NOT_FOUND)
+ pks_keystore.db_exists = false;
+
+ /*
+ * Read dbx from PKS. If dbx is not completely loaded from PKS, then this
+ * could lead to the loading of vulnerable GRUB modules and kernel binaries.
+ * So, this should be prevented by freeing up loaded dbx and db.
+ */
+ rc_dbx = read_sbvar_from_pks (0, GRUB_PKS_SBVAR_DBX, &pks_keystore.dbx, &pks_keystore.dbx_entries);
+ if (rc_dbx == GRUB_ERR_FILE_NOT_FOUND || rc_dbx == GRUB_ERR_BAD_NUMBER)
+ rc_dbx = GRUB_ERR_NONE;
+
+ if (rc_dbx != GRUB_ERR_NONE)
+ grub_pks_free_data ();
+
+ /*
+ * At this point, it's evident that PKS infrastructure exists, so the PKS
+ * keystore must be used for validating appended signatures.
+ */
+ pks_use_keystore = true;
+}
#include <grub/types.h>
#include <grub/machine/ieee1275.h>
+#define IEEE1275_CELL_INVALID ((grub_ieee1275_cell_t) -1)
+#define IEEE1275_CELL_NOT_FOUND ((grub_int32_t) -7)
+
#define GRUB_IEEE1275_CELL_FALSE ((grub_ieee1275_cell_t) 0)
#define GRUB_IEEE1275_CELL_TRUE ((grub_ieee1275_cell_t) -1)
#define PRIxGRUB_IEEE1275_CELL_T PRIxGRUB_UINT32_T
#define PRIuGRUB_IEEE1275_CELL_T PRIuGRUB_UINT32_T
+#ifdef __powerpc__
+/* The maximum object size interface name for a PKS object. */
+#define GRUB_PKS_MAX_OBJ_INTERFACE "pks-max-object-size"
+
+/* PKS read object and read sbvar interface name. */
+#define GRUB_PKS_READ_OBJ_INTERFACE "pks-read-object"
+#define GRUB_PKS_READ_SBVAR_INTERFACE "pks-read-sbvar"
+
+/* PKS read object label for secure boot version. */
+#define GRUB_SB_VERSION_KEY_NAME "SB_VERSION"
+#define GRUB_SB_VERSION_KEY_LEN (sizeof (GRUB_SB_VERSION_KEY_NAME) - 1)
+
+/* PKS consumer type for firmware. */
+#define GRUB_PKS_CONSUMER_FW ((grub_uint32_t) 1)
+
+/* PKS read secure boot variable request type for db and dbx. */
+#define GRUB_PKS_SBVAR_DB ((grub_uint32_t) 1)
+#define GRUB_PKS_SBVAR_DBX ((grub_uint32_t) 2)
+
+extern grub_int32_t
+grub_ieee1275_test (const char *interface_name);
+
+extern grub_int32_t
+grub_ieee1275_pks_max_object_size (grub_uint32_t *result);
+
+extern grub_int32_t
+grub_ieee1275_pks_read_object (const grub_uint32_t consumer, const char *label,
+ const grub_uint32_t label_len, const grub_uint32_t buffer_len,
+ grub_uint8_t *buffer, grub_uint32_t *data_len,
+ grub_uint32_t *policies);
+
+extern grub_int32_t
+grub_ieee1275_pks_read_sbvar (const grub_uint32_t sbvar_flags, const grub_uint32_t sbvar_type,
+ const grub_uint32_t buffer_len, grub_uint8_t *buffer,
+ grub_size_t *data_len);
+#endif /* __powerpc__ */
#endif /* ! GRUB_IEEE1275_MACHINE_HEADER */
--- /dev/null
+/*
+ * Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved. This
+ * program and the accompanying materials are licensed and made available
+ * under the terms and conditions of the 2-Clause BSD License which
+ * accompanies this distribution.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * https://github.com/tianocore/edk2-staging (edk2-staging repo of tianocore),
+ * the ImageAuthentication.h file under it, and here's the copyright and license.
+ *
+ * MdePkg/Include/Guid/ImageAuthentication.h
+ *
+ * Copyright 2022, 2023, 2024, 2025 IBM Corp.
+ */
+
+#ifndef PLATFORM_KEYSTORE_HEADER
+#define PLATFORM_KEYSTORE_HEADER 1
+
+#include <grub/symbol.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+
+/*
+ * It is derived from EFI_SIGNATURE_DATA
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
+ *
+ * The structure of an EFI Signature Database (ESD). */
+struct grub_esd
+{
+ /*
+ * An identifier which identifies the agent which added the signature to
+ * the list.
+ */
+ grub_packed_guid_t signature_owner;
+ /* The format of the signature is defined by the SignatureType. */
+ grub_uint8_t signature_data[];
+} GRUB_PACKED;
+typedef struct grub_esd grub_esd_t;
+
+/*
+ * It is derived from EFI_SIGNATURE_LIST
+ * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h
+ *
+ * The structure of an EFI Signature List (ESL). */
+struct grub_esl
+{
+ /* Type of the signature. GUID signature types are defined in below. */
+ grub_packed_guid_t signature_type;
+ /* Total size of the signature list, including this header. */
+ grub_uint32_t signature_list_size;
+ /* Size of the signature header which precedes the array of signatures. */
+ grub_uint32_t signature_header_size;
+ /* Size of each signature.*/
+ grub_uint32_t signature_size;
+} GRUB_PACKED;
+typedef struct grub_esl grub_esl_t;
+
+/* The structure of a PKS Signature Database (SD). */
+struct grub_pks_sd
+{
+ grub_packed_guid_t guid; /* Signature type. */
+ grub_uint8_t *data; /* Signature data. */
+ grub_size_t data_size; /* Size of signature data. */
+} GRUB_PACKED;
+typedef struct grub_pks_sd grub_pks_sd_t;
+
+/* The structure of a Platform KeyStore (PKS). */
+struct grub_pks
+{
+ grub_pks_sd_t *db; /* Signature database. */
+ grub_pks_sd_t *dbx; /* Forbidden signature database. */
+ grub_uint32_t db_entries; /* Size of signature database. */
+ grub_uint32_t dbx_entries;/* Size of forbidden signature database. */
+ bool db_exists; /* Flag to indicate if the db exists or not in PKS. */
+};
+typedef struct grub_pks grub_pks_t;
+
+#if defined(__powerpc__)
+/* Initialization of the Platform Keystore. */
+extern void
+grub_pks_keystore_init (void);
+
+/* Platform KeyStore db and dbx. */
+extern grub_pks_t *
+EXPORT_FUNC (grub_pks_get_keystore) (void);
+
+/* Free allocated memory. */
+extern void
+EXPORT_FUNC (grub_pks_free_data) (void);
+#else
+static inline grub_pks_t *
+grub_pks_get_keystore (void)
+{
+ return NULL;
+}
+
+static inline void
+grub_pks_free_data (void)
+{
+}
+#endif /* __powerpc__ */
+#endif