aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/pldm/Makefile.inc2
-rw-r--r--core/pldm/pldm-lid-files.c186
-rw-r--r--include/pldm.h7
3 files changed, 194 insertions, 1 deletions
diff --git a/core/pldm/Makefile.inc b/core/pldm/Makefile.inc
index d89e4c2..87952db 100644
--- a/core/pldm/Makefile.inc
+++ b/core/pldm/Makefile.inc
@@ -10,7 +10,7 @@ CPPFLAGS += -I$(SRC)/pldm/include/libpldm/oem/ibm/
PLDM_OBJS = pldm-mctp.o pldm-responder.o pldm-requester.o
PLDM_OBJS += pldm-base-requests.o pldm-platform-requests.o
PLDM_OBJS += pldm-bios-requests.o pldm-fru-requests.o
-PLDM_OBJS += pldm-file-io-requests.o
+PLDM_OBJS += pldm-file-io-requests.o pldm-lid-files.o
PLDM = $(PLDM_DIR)/built-in.a
$(PLDM): $(PLDM_OBJS:%=$(PLDM_DIR)/%)
diff --git a/core/pldm/pldm-lid-files.c b/core/pldm/pldm-lid-files.c
new file mode 100644
index 0000000..a46a731
--- /dev/null
+++ b/core/pldm/pldm-lid-files.c
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+// Copyright 2022 IBM Corp.
+
+#define pr_fmt(fmt) "PLDM: " fmt
+
+#include <endian.h>
+#include <lock.h>
+#include <opal-api.h>
+#include <libflash/errors.h>
+#include <libflash/ffs.h>
+#include "pldm.h"
+
+/*
+ * This struct is used to map a PNOR sections.
+ * The content is deriving from the hb_lid_ids PLDM BIOS Attribute.
+ */
+struct pldm_lid {
+ struct list_node list;
+ uint32_t start;
+ uint32_t handle;
+ uint32_t length;
+ char name[FFS_PART_NAME_MAX + 1];
+ char id[FFS_PART_NAME_MAX + 1];
+};
+
+static LIST_HEAD(lid_files);
+
+#define MEGABYTE (1024*1024)
+
+/*
+ * When using PLDM for PNOR Resource Provider operations,
+ * reserve 32 MB of VMM address space per section.
+ * Note that all of this space may not actually be used by each section.
+ */
+#define VMM_SIZE_RESERVED_PER_SECTION (32 * MEGABYTE)
+
+/*
+ * Print the attributes of lid files.
+ */
+static void print_lid_files_attr(void)
+{
+ struct pldm_lid *lid = NULL;
+
+ list_for_each(&lid_files, lid, list)
+ prlog(PR_NOTICE, "name: %s, id: %s, handle: %d, length: 0x%x, start: 0x%x\n",
+ lid->name, lid->id, lid->handle, lid->length, lid->start);
+}
+
+/*
+ * Return the number of lid files.
+ */
+static uint32_t get_lids_count(void)
+{
+ struct pldm_lid *lid = NULL;
+ uint32_t count = 0;
+
+ list_for_each(&lid_files, lid, list)
+ count++;
+
+ return count;
+}
+
+/*
+ * parse the "hb_lid_ids" string
+ * <ATTR_a>=<lid_id_1>,<ATTR_b>=<lid_id_2>
+ */
+static int parse_hb_lid_ids_string(char *str)
+{
+ struct pldm_lid *lid, *tmp;
+ const char *pp = "=";
+ char *attr, *attr_end;
+ int rc, count = 1;
+ char *lid_id;
+
+ for (char *p = strtok(str, ","); p != NULL; p = strtok(NULL, ",")) {
+ lid = zalloc(sizeof(struct pldm_lid));
+ if (!lid) {
+ prlog(PR_ERR, "Error allocating pldm_lid structure\n");
+ rc = OPAL_NO_MEM;
+ goto err;
+ }
+
+ /* parse the string <attr>=<lid_id> */
+ attr = p;
+ while ((*pp != *p) && (*p != '\0'))
+ p++;
+
+ attr_end = p;
+ lid_id = ++p;
+ *attr_end = '\0';
+
+ strcpy(lid->name, attr);
+ strcpy(lid->id, lid_id);
+
+ /* reserve 32 MB of VMM address space per section.
+ * Address 0x0 -> 0x2000000: 'fake' header flash
+ * Address 0x2000000 -> 0x4000000: lid id 1
+ * Address 0x4000000 -> 0x6000000: lid id 2
+ * ....
+ */
+ lid->start = VMM_SIZE_RESERVED_PER_SECTION * count;
+
+ /* handle and length */
+ rc = pldm_find_file_handle_by_lid_id(lid->id,
+ &lid->handle,
+ &lid->length);
+ /* OPAL_PARAMETER means that lid_id is present in hb_lid_ids,
+ * but we don't have any file attribute information in the
+ * file table, so continue on the next item.
+ */
+ if ((rc) && (rc != OPAL_PARAMETER))
+ goto err;
+
+ if (lid->length > VMM_SIZE_RESERVED_PER_SECTION) {
+ prlog(PR_ERR, "file length (0x%x) > virtual size reserved per "
+ "section (0x%x)\n",
+ lid->length, VMM_SIZE_RESERVED_PER_SECTION);
+ rc = OPAL_RESOURCE;
+ goto err;
+ }
+
+ /* add new member in the global list */
+ list_add_tail(&lid_files, &lid->list);
+
+ count++;
+ }
+
+ return OPAL_SUCCESS;
+
+err:
+ /* free all lid entries */
+ list_for_each_safe(&lid_files, lid, tmp, list)
+ free(lid);
+
+ return rc;
+}
+
+/*
+ * Parse the "hb_lid_ids" string from bios tables and complete
+ * the global list of lid files.
+ */
+static int lid_ids_to_vaddr_mapping(void)
+{
+ char *lid_ids_string = NULL;
+ int rc;
+
+ /* get lid ids string from bios tables */
+ rc = pldm_bios_get_lids_id(&lid_ids_string);
+ if (rc)
+ goto out;
+
+ /* parse the "hb_lid_ids" string */
+ rc = parse_hb_lid_ids_string(lid_ids_string);
+
+out:
+ if (lid_ids_string)
+ free(lid_ids_string);
+
+ return rc;
+}
+
+int pldm_lid_files_init(struct blocklevel_device **bl)
+{
+ uint32_t lid_files_count;
+ int rc;
+
+ if (!bl)
+ return FLASH_ERR_PARM_ERROR;
+
+ *bl = NULL;
+
+ /* convert lid ids data to pnor structure */
+ rc = lid_ids_to_vaddr_mapping();
+ if (rc)
+ goto err;
+
+ lid_files_count = get_lids_count();
+
+ prlog(PR_NOTICE, "Number of lid files: %d\n", lid_files_count);
+ print_lid_files_attr();
+
+ return OPAL_SUCCESS;
+
+err:
+ return rc;
+}
diff --git a/include/pldm.h b/include/pldm.h
index 3c23dc9..9c5369e 100644
--- a/include/pldm.h
+++ b/include/pldm.h
@@ -5,6 +5,8 @@
#ifndef __PLDM_H__
#define __PLDM_H__
+#include <skiboot.h>
+
/**
* Handle PLDM messages received from MCTP
*/
@@ -36,4 +38,9 @@ int pldm_platform_restart(void);
*/
int pldm_fru_dt_add_bmc_version(void);
+/**
+ * Convert lid ids data to pnor structure
+ */
+int pldm_lid_files_init(struct blocklevel_device **bl);
+
#endif /* __PLDM_H__ */