--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) ASPEED Technology Inc.
+ */
+
+#ifndef __ASM_AST2700_FMC_HDR_H__
+#define __ASM_AST2700_FMC_HDR_H__
+
+#include <linux/types.h>
+
+#define HDR_MAGIC 0x48545341 /* ASTH */
+#define HDR_PB_MAX 30
+
+enum prebuilt_type {
+ PBT_END_MARK = 0x0,
+
+ PBT_DDR4_PMU_TRAIN_IMEM,
+ PBT_DDR4_PMU_TRAIN_DMEM,
+ PBT_DDR4_2D_PMU_TRAIN_IMEM,
+ PBT_DDR4_2D_PMU_TRAIN_DMEM,
+ PBT_DDR5_PMU_TRAIN_IMEM,
+ PBT_DDR5_PMU_TRAIN_DMEM,
+ PBT_DP_FW,
+ PBT_UEFI_X64_AST2700,
+
+ PBT_NUM
+};
+
+struct fmc_hdr_preamble {
+ uint32_t magic;
+ uint32_t version;
+};
+
+struct fmc_hdr_body {
+ uint32_t fmc_size;
+ union {
+ struct {
+ uint32_t type;
+ uint32_t size;
+ } pbs[0];
+ uint32_t raz[29];
+ };
+};
+
+struct fmc_hdr {
+ struct fmc_hdr_preamble preamble;
+ struct fmc_hdr_body body;
+} __packed;
+
+int fmc_hdr_get_prebuilt(uint32_t type, uint32_t *ofst, uint32_t *size);
+
+#endif
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) Aspeed Technology Inc.
+ */
+
+#include <asm/arch/fmc_hdr.h>
+#include <asm/io.h>
+#include <asm/sections.h>
+#include <errno.h>
+#include <spl.h>
+#include <string.h>
+
+int fmc_hdr_get_prebuilt(uint32_t type, uint32_t *ofst, uint32_t *size)
+{
+ struct fmc_hdr_preamble *preamble;
+ struct fmc_hdr_body *body;
+ struct fmc_hdr *hdr;
+ uint32_t t, s, o;
+ int i;
+
+ if (type >= PBT_NUM)
+ return -EINVAL;
+
+ if (!ofst || !size)
+ return -EINVAL;
+
+ hdr = (struct fmc_hdr *)(_start - sizeof(*hdr));
+ preamble = &hdr->preamble;
+ body = &hdr->body;
+
+ if (preamble->magic != HDR_MAGIC)
+ return -EIO;
+
+ for (i = 0, o = sizeof(*hdr) + body->fmc_size; i < HDR_PB_MAX; ++i) {
+ t = body->pbs[i].type;
+ s = body->pbs[i].size;
+
+ /* skip if unrecognized, yet */
+ if (t >= PBT_NUM) {
+ o += s;
+ continue;
+ }
+
+ /* prebuilt end mark */
+ if (t == 0 && s == 0)
+ break;
+
+ /* return the prebuilt info if found */
+ if (t == type) {
+ *ofst = o;
+ *size = s;
+
+ goto found;
+ }
+
+ /* update offset for next prebuilt */
+ o += s;
+ }
+
+ return -ENODATA;
+
+found:
+ return 0;
+}