aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--core/Makefile.inc2
-rw-r--r--core/pel.c254
-rw-r--r--core/test/Makefile.check4
-rw-r--r--core/test/run-pel.c81
-rw-r--r--hw/fsp/fsp-elog-write.c239
-rw-r--r--include/fsp-elog.h149
-rw-r--r--include/pel.h177
8 files changed, 527 insertions, 380 deletions
diff --git a/.gitignore b/.gitignore
index fa45a12..cc55710 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,6 +26,7 @@ core/test/run-mem_region_init
core/test/run-mem_region_release_unused
core/test/run-mem_region_release_unused_noalloc
core/test/run-msg
+core/test/run-pel
core/test/run-trace
core/test/*-gcov
external/dump_trace
diff --git a/core/Makefile.inc b/core/Makefile.inc
index 714da3a..8b9a03b 100644
--- a/core/Makefile.inc
+++ b/core/Makefile.inc
@@ -6,7 +6,7 @@ CORE_OBJS += malloc.o lock.o cpu.o utils.o fdt.o opal.o interrupts.o
CORE_OBJS += timebase.o opal-msg.o pci.o pci-opal.o fast-reboot.o
CORE_OBJS += device.o exceptions.o trace.o affinity.o vpd.o
CORE_OBJS += hostservices.o platform.o nvram.o flash-nvram.o hmi.o
-CORE_OBJS += console-log.o ipmi.o time-utils.o
+CORE_OBJS += console-log.o ipmi.o time-utils.o pel.o
CORE=core/built-in.o
$(CORE): $(CORE_OBJS:%=core/%)
diff --git a/core/pel.c b/core/pel.c
new file mode 100644
index 0000000..1f6d11b
--- /dev/null
+++ b/core/pel.c
@@ -0,0 +1,254 @@
+#include <string.h>
+#include <fsp-elog.h>
+#include <device.h>
+#include <fsp.h>
+#include <pel.h>
+
+/* Create MTMS section for sapphire log */
+static void create_mtms_section(struct errorlog *elog_data,
+ char *pel_buffer, int *pel_offset)
+{
+ struct opal_mtms_section *mtms = (struct opal_mtms_section *)
+ (pel_buffer + *pel_offset);
+
+ mtms->v6header.id = ELOG_SID_MACHINE_TYPE;
+ mtms->v6header.length = MTMS_SECTION_SIZE;
+ mtms->v6header.version = OPAL_EXT_HRD_VER;
+ mtms->v6header.subtype = 0;
+ mtms->v6header.component_id = elog_data->component_id;
+
+ memset(mtms->model, 0x00, sizeof(mtms->model));
+ memcpy(mtms->model, dt_prop_get(dt_root, "model"), OPAL_SYS_MODEL_LEN);
+ memset(mtms->serial_no, 0x00, sizeof(mtms->serial_no));
+
+ memcpy(mtms->serial_no, dt_prop_get(dt_root, "system-id"),
+ OPAL_SYS_SERIAL_LEN);
+ *pel_offset += MTMS_SECTION_SIZE;
+}
+
+/* Create extended header section */
+static void create_extended_header_section(struct errorlog *elog_data,
+ char *pel_buffer, int *pel_offset)
+{
+ const char *opalmodel = NULL;
+ uint64_t extd_time;
+
+ struct opal_extended_header_section *extdhdr =
+ (struct opal_extended_header_section *)
+ (pel_buffer + *pel_offset);
+
+ extdhdr->v6header.id = ELOG_SID_EXTENDED_HEADER;
+ extdhdr->v6header.length = EXTENDED_HEADER_SECTION_SIZE;
+ extdhdr->v6header.version = OPAL_EXT_HRD_VER;
+ extdhdr->v6header.subtype = 0;
+ extdhdr->v6header.component_id = elog_data->component_id;
+
+ memset(extdhdr->model, 0x00, sizeof(extdhdr->model));
+ opalmodel = dt_prop_get(dt_root, "model");
+ memcpy(extdhdr->model, opalmodel, OPAL_SYS_MODEL_LEN);
+
+ memset(extdhdr->serial_no, 0x00, sizeof(extdhdr->serial_no));
+ memcpy(extdhdr->serial_no, dt_prop_get(dt_root, "system-id"),
+ OPAL_SYS_SERIAL_LEN);
+
+ memset(extdhdr->opal_release_version, 0x00,
+ sizeof(extdhdr->opal_release_version));
+ memset(extdhdr->opal_subsys_version, 0x00,
+ sizeof(extdhdr->opal_subsys_version));
+
+ fsp_rtc_get_cached_tod(&extdhdr->extended_header_date, &extd_time);
+ extdhdr->extended_header_time = extd_time >> 32;
+ extdhdr->opal_symid_len = 0;
+
+ *pel_offset += EXTENDED_HEADER_SECTION_SIZE;
+}
+
+/* set src type */
+static void settype(struct opal_src_section *src, uint8_t src_type)
+{
+ char type[4];
+ sprintf(type, "%02X", src_type);
+ memcpy(src->srcstring, type, 2);
+}
+
+/* set SRC subsystem type */
+static void setsubsys(struct opal_src_section *src, uint8_t src_subsys)
+{
+ char subsys[4];
+ sprintf(subsys, "%02X", src_subsys);
+ memcpy(src->srcstring+2, subsys, 2);
+}
+
+/* Ser reason code of SRC */
+static void setrefcode(struct opal_src_section *src, uint16_t src_refcode)
+{
+ char refcode[8];
+ sprintf(refcode, "%04X", src_refcode);
+ memcpy(src->srcstring+4, refcode, 4);
+}
+
+/* Create SRC section of OPAL log */
+static void create_src_section(struct errorlog *elog_data,
+ char *pel_buffer, int *pel_offset)
+{
+ struct opal_src_section *src = (struct opal_src_section *)
+ (pel_buffer + *pel_offset);
+
+ src->v6header.id = ELOG_SID_PRIMARY_SRC;
+ src->v6header.length = SRC_SECTION_SIZE;
+ src->v6header.version = OPAL_ELOG_VERSION;
+ src->v6header.subtype = OPAL_ELOG_SST;
+ src->v6header.component_id = elog_data->component_id;
+
+ src->version = OPAL_SRC_SEC_VER;
+ src->flags = 0;
+ src->wordcount = OPAL_SRC_MAX_WORD_COUNT;
+ src->srclength = SRC_LENGTH;
+ settype(src, OPAL_SRC_TYPE_ERROR);
+ setsubsys(src, OPAL_FAILING_SUBSYSTEM);
+ setrefcode(src, elog_data->reason_code);
+ memset(src->hexwords, 0 , (8 * 4));
+ src->hexwords[0] = OPAL_SRC_FORMAT;
+ src->hexwords[4] = elog_data->additional_info[0];
+ src->hexwords[5] = elog_data->additional_info[1];
+ src->hexwords[6] = elog_data->additional_info[2];
+ src->hexwords[7] = elog_data->additional_info[3];
+ *pel_offset += SRC_SECTION_SIZE;
+}
+
+/* Create user header section */
+static void create_user_header_section(struct errorlog *elog_data,
+ char *pel_buffer, int *pel_offset)
+{
+ struct opal_user_header_section *usrhdr =
+ (struct opal_user_header_section *)
+ (pel_buffer + *pel_offset);
+
+ usrhdr->v6header.id = ELOG_SID_USER_HEADER;
+ usrhdr->v6header.length = USER_HEADER_SECTION_SIZE;
+ usrhdr->v6header.version = OPAL_ELOG_VERSION;
+ usrhdr->v6header.subtype = OPAL_ELOG_SST;
+ usrhdr->v6header.component_id = elog_data->component_id;
+
+ usrhdr->subsystem_id = elog_data->subsystem_id;
+ usrhdr->event_scope = 0;
+ usrhdr->event_severity = elog_data->event_severity;
+ usrhdr->event_type = elog_data->event_subtype;
+
+ if (elog_data->elog_origin == ORG_SAPPHIRE)
+ usrhdr->action_flags = ERRL_ACTION_REPORT;
+ else
+ usrhdr->action_flags = ERRL_ACTION_NONE;
+
+ *pel_offset += USER_HEADER_SECTION_SIZE;
+}
+
+/* Create private header section */
+static void create_private_header_section(struct errorlog *elog_data,
+ char *pel_buffer, int *pel_offset)
+{
+ uint64_t ctime;
+ struct opal_private_header_section *privhdr =
+ (struct opal_private_header_section *)
+ pel_buffer;
+
+ privhdr->v6header.id = ELOG_SID_PRIVATE_HEADER;
+ privhdr->v6header.length = PRIVATE_HEADER_SECTION_SIZE;
+ privhdr->v6header.version = OPAL_ELOG_VERSION;
+ privhdr->v6header.subtype = OPAL_ELOG_SST;
+ privhdr->v6header.component_id = elog_data->component_id;
+ privhdr->plid = elog_data->plid;
+
+ fsp_rtc_get_cached_tod(&privhdr->create_date, &ctime);
+ privhdr->create_time = ctime >> 32;
+ privhdr->section_count = 5;
+
+ privhdr->creator_subid_hi = 0x00;
+ privhdr->creator_subid_lo = 0x00;
+
+ if (elog_data->elog_origin == ORG_SAPPHIRE)
+ privhdr->creator_id = OPAL_CID_SAPPHIRE;
+ else
+ privhdr->creator_id = OPAL_CID_POWERNV;
+
+ privhdr->log_entry_id = elog_data->plid; /*entry id is updated by FSP*/
+
+ *pel_offset += PRIVATE_HEADER_SECTION_SIZE;
+}
+
+static void create_user_defined_section(struct errorlog *elog_data,
+ char *pel_buffer, int *pel_offset)
+{
+ char *dump = (char *)pel_buffer + *pel_offset;
+ char *opal_buf = (char *)elog_data->user_data_dump;
+ struct opal_user_section *usrhdr;
+ struct elog_user_data_section *opal_usr_data;
+ struct opal_private_header_section *privhdr =
+ (struct opal_private_header_section *)pel_buffer;
+ int i;
+
+ for (i = 0; i < elog_data->user_section_count; i++) {
+
+ usrhdr = (struct opal_user_section *)dump;
+ opal_usr_data = (struct elog_user_data_section *)opal_buf;
+
+ usrhdr->v6header.id = ELOG_SID_USER_DEFINED;
+ usrhdr->v6header.version = OPAL_ELOG_VERSION;
+ usrhdr->v6header.length = sizeof(struct opal_v6_header) +
+ opal_usr_data->size;
+ usrhdr->v6header.subtype = OPAL_ELOG_SST;
+ usrhdr->v6header.component_id = elog_data->component_id;
+
+ memcpy(usrhdr->dump, opal_buf, opal_usr_data->size);
+ *pel_offset += usrhdr->v6header.length;
+ dump += usrhdr->v6header.length;
+ opal_buf += opal_usr_data->size;
+ privhdr->section_count++;
+ }
+}
+
+static size_t pel_user_section_size(struct errorlog *elog_data)
+{
+ int i;
+ size_t total = 0;
+ char *opal_buf = (char *)elog_data->user_data_dump;
+ struct elog_user_data_section *opal_usr_data;
+
+ for (i = 0; i < elog_data->user_section_count; i++) {
+ opal_usr_data = (struct elog_user_data_section *)opal_buf;
+ total += sizeof(struct opal_v6_header) +
+ opal_usr_data->size;
+ opal_buf += opal_usr_data->size;
+ }
+
+ return total;
+}
+
+size_t pel_size(struct errorlog *elog_data)
+{
+ return PEL_MIN_SIZE + pel_user_section_size(elog_data);
+}
+
+/* Converts an OPAL errorlog into a PEL formatted log */
+int create_pel_log(struct errorlog *elog_data, char *pel_buffer,
+ size_t pel_buffer_size)
+{
+ int pel_offset = 0;
+
+ if (pel_buffer_size < pel_size(elog_data)) {
+ prerror("PEL buffer too small to create record");
+ return 0;
+ }
+
+ memset(pel_buffer, 0, pel_buffer_size);
+
+ create_private_header_section(elog_data, pel_buffer, &pel_offset);
+ create_user_header_section(elog_data, pel_buffer, &pel_offset);
+ create_src_section(elog_data, pel_buffer, &pel_offset);
+ create_extended_header_section(elog_data, pel_buffer, &pel_offset);
+ create_mtms_section(elog_data, pel_buffer, &pel_offset);
+ if (elog_data->user_section_count)
+ create_user_defined_section(elog_data, pel_buffer, &pel_offset);
+
+ return pel_offset;
+}
diff --git a/core/test/Makefile.check b/core/test/Makefile.check
index 8645001..3fe4530 100644
--- a/core/test/Makefile.check
+++ b/core/test/Makefile.check
@@ -1,5 +1,5 @@
# -*-Makefile-*-
-CORE_TEST := core/test/run-device core/test/run-mem_region core/test/run-malloc core/test/run-malloc-speed core/test/run-mem_region_init core/test/run-mem_region_release_unused core/test/run-mem_region_release_unused_noalloc core/test/run-trace core/test/run-msg
+CORE_TEST := core/test/run-device core/test/run-mem_region core/test/run-malloc core/test/run-malloc-speed core/test/run-mem_region_init core/test/run-mem_region_release_unused core/test/run-mem_region_release_unused_noalloc core/test/run-trace core/test/run-msg core/test/run-pel
check: $(CORE_TEST:%=%-check) $(CORE_TEST:%=%-gcov-run)
@@ -16,7 +16,7 @@ core/test/stubs.o: core/test/stubs.c
$(CORE_TEST) : core/test/stubs.o
-$(CORE_TEST) : % : %.c
+$(CORE_TEST) : % : %.c
$(HOSTCC) $(HOSTCFLAGS) -O0 -g -I include -I . -I libfdt -o $@ $< core/test/stubs.o
$(CORE_TEST): % : %.d
diff --git a/core/test/run-pel.c b/core/test/run-pel.c
new file mode 100644
index 0000000..b7a5b26
--- /dev/null
+++ b/core/test/run-pel.c
@@ -0,0 +1,81 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Test for our PEL record generation. Currently this doesn't actually
+ * test that the records we generate are correct, but it at least lets
+ * us run valgrind over the generation routines to check for buffer
+ * overflows, etc.
+ */
+
+#include <skiboot.h>
+#include <inttypes.h>
+#include <assert.h>
+#include <pel.h>
+#include <errorlog.h>
+
+#define TEST_ERROR 0x1234
+#define TEST_SUBSYS 0x5678
+
+DEFINE_LOG_ENTRY(TEST_ERROR, OPAL_PLATFORM_ERR_EVT, TEST_SUBSYS,
+ OPAL_PLATFORM_FIRMWARE, OPAL_INFO,
+ OPAL_NA, NULL);
+
+#include "../pel.c"
+
+struct dt_node *dt_root = NULL;
+char dt_prop[] = "DUMMY DT PROP";
+const void *dt_prop_get(const struct dt_node *node __unused, const char *prop __unused)
+{
+ return dt_prop;
+}
+
+int fsp_rtc_get_cached_tod(uint32_t *year_month_day,
+ uint64_t *hour_minute_second_millisecond)
+{
+ *year_month_day = 0;
+ *hour_minute_second_millisecond = 0;
+
+ return 0;
+}
+
+int main(void)
+{
+ char *pel_buf;
+ size_t size;
+ struct errorlog *elog;
+ struct opal_err_info *opal_err_info = &err_TEST_ERROR;
+
+ elog = malloc(sizeof(struct errorlog));
+ pel_buf = malloc(PEL_MIN_SIZE + 4);
+ assert(elog);
+ assert(pel_buf);
+
+ memset(elog, 0, sizeof(struct errorlog));
+
+ elog->error_event_type = opal_err_info->err_type;
+ elog->component_id = opal_err_info->cmp_id;
+ elog->subsystem_id = opal_err_info->subsystem;
+ elog->event_severity = opal_err_info->sev;
+ elog->event_subtype = opal_err_info->event_subtype;
+ elog->reason_code = opal_err_info->reason_code;
+ elog->elog_origin = ORG_SAPPHIRE;
+
+ size = pel_size(elog);
+ printf("PEL Size: %ld\n", size);
+ assert(size == create_pel_log(elog, pel_buf, size));
+
+ return 0;
+}
diff --git a/hw/fsp/fsp-elog-write.c b/hw/fsp/fsp-elog-write.c
index c4c94ed..7169aa3 100644
--- a/hw/fsp/fsp-elog-write.c
+++ b/hw/fsp/fsp-elog-write.c
@@ -31,6 +31,7 @@
#include <errno.h>
#include <fsp-elog.h>
#include <timebase.h>
+#include <pel.h>
/*
* Maximum number buffers that are pre-allocated
@@ -72,7 +73,6 @@ static uint32_t elog_plid_fsp_commit = -1;
enum elog_head_state elog_write_to_host_head_state = ELOG_STATE_NONE;
/* Need forward declaration because of Circular dependency */
-static int create_opal_event(struct errorlog *elog_data, char *pel_buffer);
static int opal_send_elog_to_fsp(void);
void log_error(struct opal_err_info *e_info, void *data, uint16_t size,
@@ -275,8 +275,9 @@ static void opal_commit_elog_in_host(void)
(elog_write_to_host_head_state == ELOG_STATE_NONE)) {
buf = list_top(&elog_write_to_host_pending,
struct errorlog, link);
- buf->log_size = create_opal_event(buf,
- (char *)elog_write_to_host_buffer);
+ buf->log_size = create_pel_log(buf,
+ (char *)elog_write_to_host_buffer,
+ ELOG_WRITE_TO_HOST_BUFFER_SIZE);
elog_write_to_host_head_state = ELOG_STATE_FETCHED_DATA;
opal_update_pending_evt(OPAL_EVENT_ERROR_LOG_AVAIL,
OPAL_EVENT_ERROR_LOG_AVAIL);
@@ -386,8 +387,9 @@ static int opal_send_elog_to_fsp(void)
head = list_top(&elog_write_to_fsp_pending,
struct errorlog, link);
elog_plid_fsp_commit = head->plid;
- head->log_size = create_opal_event(head,
- (char *)elog_write_to_fsp_buffer);
+ head->log_size = create_pel_log(head,
+ (char *)elog_write_to_fsp_buffer,
+ ELOG_WRITE_TO_FSP_BUFFER_SIZE);
rc = fsp_opal_elog_write(head->log_size);
unlock(&elog_write_lock);
return rc;
@@ -403,8 +405,9 @@ static int opal_push_logs_sync_to_fsp(struct errorlog *buf)
int rc = OPAL_SUCCESS;
lock(&elog_panic_write_lock);
- opal_elog_size = create_opal_event(buf,
- (char *)elog_panic_write_buffer);
+ opal_elog_size = create_pel_log(buf,
+ (char *)elog_panic_write_buffer,
+ ELOG_PANIC_WRITE_BUFFER_SIZE);
elog_msg = fsp_mkmsg(FSP_CMD_CREATE_ERRLOG, 3, opal_elog_size,
0, PSI_DMA_ELOG_PANIC_WRITE_BUF);
@@ -492,228 +495,6 @@ int opal_elog_update_user_dump(struct errorlog *buf, unsigned char *data,
return 0;
}
-/* Create MTMS section for sapphire log */
-static void create_mtms_section(struct errorlog *elog_data,
- char *pel_buffer, int *pel_offset)
-{
- struct opal_mtms_section *mtms = (struct opal_mtms_section *)
- (pel_buffer + *pel_offset);
-
- mtms->v6header.id = ELOG_SID_MACHINE_TYPE;
- mtms->v6header.length = MTMS_SECTION_SIZE;
- mtms->v6header.version = OPAL_EXT_HRD_VER;
- mtms->v6header.subtype = 0;
- mtms->v6header.component_id = elog_data->component_id;
-
- memset(mtms->model, 0x00, sizeof(mtms->model));
- memcpy(mtms->model, dt_prop_get(dt_root, "model"), OPAL_SYS_MODEL_LEN);
- memset(mtms->serial_no, 0x00, sizeof(mtms->serial_no));
-
- memcpy(mtms->serial_no, dt_prop_get(dt_root, "system-id"),
- OPAL_SYS_SERIAL_LEN);
- *pel_offset += MTMS_SECTION_SIZE;
-}
-
-/* Create extended header section */
-static void create_extended_header_section(struct errorlog *elog_data,
- char *pel_buffer, int *pel_offset)
-{
- const char *opalmodel = NULL;
- uint64_t extd_time;
-
- struct opal_extended_header_section *extdhdr =
- (struct opal_extended_header_section *)
- (pel_buffer + *pel_offset);
-
- extdhdr->v6header.id = ELOG_SID_EXTENDED_HEADER;
- extdhdr->v6header.length = EXTENDED_HEADER_SECTION_SIZE;
- extdhdr->v6header.version = OPAL_EXT_HRD_VER;
- extdhdr->v6header.subtype = 0;
- extdhdr->v6header.component_id = elog_data->component_id;
-
- memset(extdhdr->model, 0x00, sizeof(extdhdr->model));
- opalmodel = dt_prop_get(dt_root, "model");
- memcpy(extdhdr->model, opalmodel, OPAL_SYS_MODEL_LEN);
-
- memset(extdhdr->serial_no, 0x00, sizeof(extdhdr->serial_no));
- memcpy(extdhdr->serial_no, dt_prop_get(dt_root, "system-id"),
- OPAL_SYS_SERIAL_LEN);
-
- memset(extdhdr->opal_release_version, 0x00,
- sizeof(extdhdr->opal_release_version));
- memset(extdhdr->opal_subsys_version, 0x00,
- sizeof(extdhdr->opal_subsys_version));
-
- fsp_rtc_get_cached_tod(&extdhdr->extended_header_date, &extd_time);
- extdhdr->extended_header_time = extd_time >> 32;
- extdhdr->opal_symid_len = 0;
- memset(extdhdr->opalsymid, 0x00, sizeof(extdhdr->opalsymid));
-
- *pel_offset += EXTENDED_HEADER_SECTION_SIZE;
-}
-
-/* set src type */
-static void settype(struct opal_src_section *src, uint8_t src_type)
-{
- char type[4];
- sprintf(type, "%02X", src_type);
- memcpy(src->srcstring, type, 2);
-}
-
-/* set SRC subsystem type */
-static void setsubsys(struct opal_src_section *src, uint8_t src_subsys)
-{
- char subsys[4];
- sprintf(subsys, "%02X", src_subsys);
- memcpy(src->srcstring+2, subsys, 2);
-}
-
-/* Ser reason code of SRC */
-static void setrefcode(struct opal_src_section *src, uint16_t src_refcode)
-{
- char refcode[8];
- sprintf(refcode, "%04X", src_refcode);
- memcpy(src->srcstring+4, refcode, 4);
-}
-
-/* Create SRC section of OPAL log */
-static void create_src_section(struct errorlog *elog_data,
- char *pel_buffer, int *pel_offset)
-{
- struct opal_src_section *src = (struct opal_src_section *)
- (pel_buffer + *pel_offset);
-
- src->v6header.id = ELOG_SID_PRIMARY_SRC;
- src->v6header.length = SRC_SECTION_SIZE;
- src->v6header.version = OPAL_ELOG_VERSION;
- src->v6header.subtype = OPAL_ELOG_SST;
- src->v6header.component_id = elog_data->component_id;
-
- src->version = OPAL_SRC_SEC_VER;
- src->flags = 0;
- src->wordcount = OPAL_SRC_MAX_WORD_COUNT;
- src->srclength = SRC_LENGTH;
- settype(src, OPAL_SRC_TYPE_ERROR);
- setsubsys(src, OPAL_FAILING_SUBSYSTEM);
- setrefcode(src, elog_data->reason_code);
- memset(src->hexwords, 0 , (8 * 4));
- src->hexwords[0] = OPAL_SRC_FORMAT;
- src->hexwords[4] = elog_data->additional_info[0];
- src->hexwords[5] = elog_data->additional_info[1];
- src->hexwords[6] = elog_data->additional_info[2];
- src->hexwords[7] = elog_data->additional_info[3];
- *pel_offset += SRC_SECTION_SIZE;
-}
-
-/* Create user header section */
-static void create_user_header_section(struct errorlog *elog_data,
- char *pel_buffer, int *pel_offset)
-{
- struct opal_user_header_section *usrhdr =
- (struct opal_user_header_section *)
- (pel_buffer + *pel_offset);
-
- usrhdr->v6header.id = ELOG_SID_USER_HEADER;
- usrhdr->v6header.length = USER_HEADER_SECTION_SIZE;
- usrhdr->v6header.version = OPAL_ELOG_VERSION;
- usrhdr->v6header.subtype = OPAL_ELOG_SST;
- usrhdr->v6header.component_id = elog_data->component_id;
-
- usrhdr->subsystem_id = elog_data->subsystem_id;
- usrhdr->event_scope = 0;
- usrhdr->event_severity = elog_data->event_severity;
- usrhdr->event_type = elog_data->event_subtype;
-
- if (elog_data->elog_origin == ORG_SAPPHIRE)
- usrhdr->action_flags = ERRL_ACTION_REPORT;
- else
- usrhdr->action_flags = ERRL_ACTION_NONE;
-
- *pel_offset += USER_HEADER_SECTION_SIZE;
-}
-
-/* Create private header section */
-static void create_private_header_section(struct errorlog *elog_data,
- char *pel_buffer, int *pel_offset)
-{
- uint64_t ctime;
- struct opal_private_header_section *privhdr =
- (struct opal_private_header_section *)
- pel_buffer;
-
- privhdr->v6header.id = ELOG_SID_PRIVATE_HEADER;
- privhdr->v6header.length = PRIVATE_HEADER_SECTION_SIZE;
- privhdr->v6header.version = OPAL_ELOG_VERSION;
- privhdr->v6header.subtype = OPAL_ELOG_SST;
- privhdr->v6header.component_id = elog_data->component_id;
- privhdr->plid = elog_data->plid;
-
- fsp_rtc_get_cached_tod(&privhdr->create_date, &ctime);
- privhdr->create_time = ctime >> 32;
- privhdr->section_count = 5;
-
- privhdr->creator_subid_hi = 0x00;
- privhdr->creator_subid_lo = 0x00;
-
- if (elog_data->elog_origin == ORG_SAPPHIRE)
- privhdr->creator_id = OPAL_CID_SAPPHIRE;
- else
- privhdr->creator_id = OPAL_CID_POWERNV;
-
- privhdr->log_entry_id = elog_data->plid; /*entry id is updated by FSP*/
-
- *pel_offset += PRIVATE_HEADER_SECTION_SIZE;
-}
-
-static void create_user_defined_section(struct errorlog *elog_data,
- char *pel_buffer, int *pel_offset)
-{
- char *dump = (char *)pel_buffer + *pel_offset;
- char *opal_buf = (char *)elog_data->user_data_dump;
- struct opal_user_section *usrhdr;
- struct elog_user_data_section *opal_usr_data;
- struct opal_private_header_section *privhdr =
- (struct opal_private_header_section *)pel_buffer;
- int i;
-
- for (i = 0; i < elog_data->user_section_count; i++) {
-
- usrhdr = (struct opal_user_section *)dump;
- opal_usr_data = (struct elog_user_data_section *)opal_buf;
-
- usrhdr->v6header.id = ELOG_SID_USER_DEFINED;
- usrhdr->v6header.version = OPAL_ELOG_VERSION;
- usrhdr->v6header.length = sizeof(struct opal_v6_header) +
- opal_usr_data->size;
- usrhdr->v6header.subtype = OPAL_ELOG_SST;
- usrhdr->v6header.component_id = elog_data->component_id;
-
- memcpy(usrhdr->dump, opal_buf, opal_usr_data->size);
- *pel_offset += usrhdr->v6header.length;
- dump += usrhdr->v6header.length;
- opal_buf += opal_usr_data->size;
- privhdr->section_count++;
- }
-}
-
-/* Create all require section of PEL log and write to TCE buffer */
-static int create_opal_event(struct errorlog *elog_data, char *pel_buffer)
-{
- int pel_offset = 0;
-
- memset(pel_buffer, 0, PSI_DMA_ELOG_WR_TO_HOST_BUF_SZ);
-
- create_private_header_section(elog_data, pel_buffer, &pel_offset);
- create_user_header_section(elog_data, pel_buffer, &pel_offset);
- create_src_section(elog_data, pel_buffer, &pel_offset);
- create_extended_header_section(elog_data, pel_buffer, &pel_offset);
- create_mtms_section(elog_data, pel_buffer, &pel_offset);
- if (elog_data->user_section_count)
- create_user_defined_section(elog_data, pel_buffer, &pel_offset);
-
- return pel_offset;
-}
-
/* Pre-allocate memory for writing error log to FSP */
static int init_elog_write_free_list(uint32_t num_entries)
{
diff --git a/include/fsp-elog.h b/include/fsp-elog.h
index fa76219..abf3972 100644
--- a/include/fsp-elog.h
+++ b/include/fsp-elog.h
@@ -15,6 +15,7 @@
*/
#include <opal.h>
#include <errorlog.h>
+#include <pel.h>
#ifndef __ELOG_H
#define __ELOG_H
@@ -192,154 +193,6 @@ enum opal_reasoncode {
= OPAL_FP | 0x10,
};
-/* Data Structures for PEL data. */
-
-#define PRIVATE_HEADER_SECTION_SIZE 48
-#define USER_HEADER_SECTION_SIZE 24
-#define SRC_SECTION_SIZE 80
-#define SRC_SUBSECTION_SIZE 4
-#define SRC_LENGTH 72
-#define OPAL_MAX_SRC_BYTES 32
-#define EXTENDED_HEADER_SECTION_SIZE 76
-#define MTMS_SECTION_SIZE 28
-#define IO_EVENT_SECTION_SIZE 16
-
-#define OPAL_ELOG_VERSION 1
-#define OPAL_ELOG_SST 0
-#define OPAL_SRC_MAX_WORD_COUNT 8
-
-#define OPAL_SRC_FORMAT 0x80
-#define OPAL_FAILING_SUBSYSTEM 0x82
-
-#define OPAL_SYS_MODEL_LEN 8
-#define OPAL_SYS_SERIAL_LEN 12
-#define OPAL_VER_LEN 16
-#define OPAL_SYMPID_LEN 80
-#define OPAL_RC_NONE 0
-
-#define OPAL_IO_MAX_RPC_DATA 216
-#define OPAL_SRC_SEC_VER 0x02
-#define OPAL_EXT_HRD_VER 0x01
-
-/* Error log reporting action */
-#define ERRL_ACTION_REPORT 0x2000
-#define ERRL_ACTION_NONE 0x0000
-
-enum elogSectionId {
- ELOG_SID_PRIVATE_HEADER = 0x5048, /* PH */
- ELOG_SID_USER_HEADER = 0x5548, /* UH */
- ELOG_SID_EXTENDED_HEADER = 0x4548, /* EH */
- ELOG_SID_PRIMARY_SRC = 0x5053, /* PS */
- ELOG_SID_MACHINE_TYPE = 0x4D54, /* MT */
- ELOG_SID_SECONDARY_SRC = 0x5353, /* SS */
- ELOG_SID_CALL_HOME = 0x4348, /* CH */
- ELOG_SID_DUMP_LOCATOR = 0x4448, /* DH */
- ELOG_SID_SOFTWARE_ERROR = 0x5357, /* SW */
- ELOG_SID_PARTITION = 0x4C50, /* LP */
- ELOG_SID_LOGICAL_RESOURCE = 0x4C52, /* LR */
- ELOG_SID_HMC_ID = 0x484D, /* HM */
- ELOG_SID_EPOW = 0x4550, /* EP */
- ELOG_SID_IO_EVENT = 0x4945, /* IE */
- ELOG_SID_MFG_INFORMATION = 0x4D49, /* MI */
- ELOG_SID_USER_DEFINED = 0x5544 /* UD */
-};
-
-struct opal_v6_header {
- enum elogSectionId id:16; /* section id */
- uint16_t length; /* section length */
- uint8_t version; /* section version */
- uint8_t subtype; /* section sub-type id */
- uint16_t component_id; /* component id of section creator */
-};
-
-/* opal_srctype */
-#define OPAL_SRC_TYPE_ERROR 0xBB
-
-#define OPAL_CID_SAPPHIRE 'K' /* creator ID for sapphire log */
-#define OPAL_CID_POWERNV 'P' /* creator ID for powernv log */
-
-/* Origin of error, elog_origin */
-#define ORG_SAPPHIRE 1
-#define ORG_POWERNV 2
-
-/* MAX time for error log commit */
-#define ERRORLOG_TIMEOUT_INTERVAL 180
-
-/*struct opal_private head section_ */
-struct opal_private_header_section {
-
- struct opal_v6_header v6header;
- uint32_t create_date;
- uint32_t create_time;
- uint32_t commit_date;
- uint32_t commit_time;
-
- uint32_t creator_id:8; /* subsystem component id */
- uint32_t reserved_0:16;
- uint32_t section_count:8; /* number of sections in log */
- uint32_t reserved_1;
- uint32_t creator_subid_hi;
- uint32_t creator_subid_lo;
- uint32_t plid; /* platform log id */
- uint32_t log_entry_id; /* Unique log entry id */
-};
-
-/* opal user header section */
-struct opal_user_header_section {
-
- struct opal_v6_header v6header;
-
- uint8_t subsystem_id; /* subsystem id */
- uint8_t event_scope;
- uint8_t event_severity;
- uint8_t event_type; /* error/event severity */
-
- uint32_t reserved_0;
- uint16_t reserved_1;
- uint16_t action_flags; /* error action code */
- uint32_t reserved_2;
-};
-
-struct opal_src_section {
- struct opal_v6_header v6header;
- uint8_t version;
- uint8_t flags;
- uint8_t reserved_0;
- uint8_t wordcount;
- uint16_t reserved_1;
- uint16_t srclength;
- uint32_t hexwords[OPAL_SRC_MAX_WORD_COUNT];
- char srcstring[OPAL_MAX_SRC_BYTES];
-};
-
-struct opal_extended_header_section {
- struct opal_v6_header v6header;
- char model[OPAL_SYS_MODEL_LEN];
- char serial_no[OPAL_SYS_SERIAL_LEN];
- char opal_release_version[OPAL_VER_LEN];
- char opal_subsys_version[OPAL_VER_LEN];
- uint16_t reserved_0;
- uint32_t extended_header_date;
- uint32_t extended_header_time;
- uint16_t reserved_1;
- uint8_t reserved_2;
- uint8_t opal_symid_len;
- char opalsymid[OPAL_SYMPID_LEN];
-};
-
-/* opal MTMS section */
-struct opal_mtms_section {
- struct opal_v6_header v6header;
- char model[OPAL_SYS_MODEL_LEN];
- char serial_no[OPAL_SYS_SERIAL_LEN];
-};
-
-/* User defined section */
-struct opal_user_section {
- struct opal_v6_header v6header;
- char dump[1];
-};
-
struct opal_err_info {
uint32_t reason_code;
uint8_t err_type;
diff --git a/include/pel.h b/include/pel.h
new file mode 100644
index 0000000..6c06de8
--- /dev/null
+++ b/include/pel.h
@@ -0,0 +1,177 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __PEL_H
+#define __PEL_H
+
+/* Data Structures for PEL data. */
+
+#define PRIVATE_HEADER_SECTION_SIZE 48
+#define USER_HEADER_SECTION_SIZE 24
+#define SRC_SECTION_SIZE 80
+#define SRC_SUBSECTION_SIZE 4
+#define SRC_LENGTH 72
+#define OPAL_MAX_SRC_BYTES 32
+#define EXTENDED_HEADER_SECTION_SIZE 76
+#define MTMS_SECTION_SIZE 28
+#define IO_EVENT_SECTION_SIZE 16
+
+#define OPAL_ELOG_VERSION 1
+#define OPAL_ELOG_SST 0
+#define OPAL_SRC_MAX_WORD_COUNT 8
+
+#define OPAL_SRC_FORMAT 0x80
+#define OPAL_FAILING_SUBSYSTEM 0x82
+
+#define OPAL_SYS_MODEL_LEN 8
+#define OPAL_SYS_SERIAL_LEN 12
+#define OPAL_VER_LEN 16
+#define OPAL_SYMPID_LEN 80
+#define OPAL_RC_NONE 0
+
+#define OPAL_IO_MAX_RPC_DATA 216
+#define OPAL_SRC_SEC_VER 0x02
+#define OPAL_EXT_HRD_VER 0x01
+
+/* Error log reporting action */
+#define ERRL_ACTION_REPORT 0x2000
+#define ERRL_ACTION_NONE 0x0000
+
+enum elogSectionId {
+ ELOG_SID_PRIVATE_HEADER = 0x5048, /* PH */
+ ELOG_SID_USER_HEADER = 0x5548, /* UH */
+ ELOG_SID_EXTENDED_HEADER = 0x4548, /* EH */
+ ELOG_SID_PRIMARY_SRC = 0x5053, /* PS */
+ ELOG_SID_MACHINE_TYPE = 0x4D54, /* MT */
+ ELOG_SID_SECONDARY_SRC = 0x5353, /* SS */
+ ELOG_SID_CALL_HOME = 0x4348, /* CH */
+ ELOG_SID_DUMP_LOCATOR = 0x4448, /* DH */
+ ELOG_SID_SOFTWARE_ERROR = 0x5357, /* SW */
+ ELOG_SID_PARTITION = 0x4C50, /* LP */
+ ELOG_SID_LOGICAL_RESOURCE = 0x4C52, /* LR */
+ ELOG_SID_HMC_ID = 0x484D, /* HM */
+ ELOG_SID_EPOW = 0x4550, /* EP */
+ ELOG_SID_IO_EVENT = 0x4945, /* IE */
+ ELOG_SID_MFG_INFORMATION = 0x4D49, /* MI */
+ ELOG_SID_USER_DEFINED = 0x5544 /* UD */
+};
+
+
+struct opal_v6_header {
+ enum elogSectionId id:16; /* section id */
+ uint16_t length; /* section length */
+ uint8_t version; /* section version */
+ uint8_t subtype; /* section sub-type id */
+ uint16_t component_id; /* component id of section creator */
+};
+
+/* opal_srctype */
+#define OPAL_SRC_TYPE_ERROR 0xBB
+
+#define OPAL_CID_SAPPHIRE 'K' /* creator ID for sapphire log */
+#define OPAL_CID_POWERNV 'P' /* creator ID for powernv log */
+
+/* Origin of error, elog_origin */
+#define ORG_SAPPHIRE 1
+#define ORG_POWERNV 2
+
+/* MAX time for error log commit */
+#define ERRORLOG_TIMEOUT_INTERVAL 180
+
+/*struct opal_private head section_ */
+struct opal_private_header_section {
+
+ struct opal_v6_header v6header;
+ uint32_t create_date;
+ uint32_t create_time;
+ uint32_t commit_date;
+ uint32_t commit_time;
+
+ uint32_t creator_id:8; /* subsystem component id */
+ uint32_t reserved_0:16;
+ uint32_t section_count:8; /* number of sections in log */
+ uint32_t reserved_1;
+ uint32_t creator_subid_hi;
+ uint32_t creator_subid_lo;
+ uint32_t plid; /* platform log id */
+ uint32_t log_entry_id; /* Unique log entry id */
+};
+
+/* opal user header section */
+struct opal_user_header_section {
+
+ struct opal_v6_header v6header;
+
+ uint8_t subsystem_id; /* subsystem id */
+ uint8_t event_scope;
+ uint8_t event_severity;
+ uint8_t event_type; /* error/event severity */
+
+ uint32_t reserved_0;
+ uint16_t reserved_1;
+ uint16_t action_flags; /* error action code */
+ uint32_t reserved_2;
+};
+
+struct opal_src_section {
+ struct opal_v6_header v6header;
+ uint8_t version;
+ uint8_t flags;
+ uint8_t reserved_0;
+ uint8_t wordcount;
+ uint16_t reserved_1;
+ uint16_t srclength;
+ uint32_t hexwords[OPAL_SRC_MAX_WORD_COUNT];
+ char srcstring[OPAL_MAX_SRC_BYTES];
+};
+
+struct opal_extended_header_section {
+ struct opal_v6_header v6header;
+ char model[OPAL_SYS_MODEL_LEN];
+ char serial_no[OPAL_SYS_SERIAL_LEN];
+ char opal_release_version[OPAL_VER_LEN];
+ char opal_subsys_version[OPAL_VER_LEN];
+ uint16_t reserved_0;
+ uint32_t extended_header_date;
+ uint32_t extended_header_time;
+ uint16_t reserved_1;
+ uint8_t reserved_2;
+ uint8_t opal_symid_len;
+ char opalsymid[OPAL_SYMPID_LEN];
+};
+
+/* opal MTMS section */
+struct opal_mtms_section {
+ struct opal_v6_header v6header;
+ char model[OPAL_SYS_MODEL_LEN];
+ char serial_no[OPAL_SYS_SERIAL_LEN];
+};
+
+/* User defined section */
+struct opal_user_section {
+ struct opal_v6_header v6header;
+ char dump[1];
+};
+
+/* The minimum size of a PEL record */
+#define PEL_MIN_SIZE (PRIVATE_HEADER_SECTION_SIZE + USER_HEADER_SECTION_SIZE \
+ + SRC_SECTION_SIZE + EXTENDED_HEADER_SECTION_SIZE \
+ + MTMS_SECTION_SIZE)
+
+size_t pel_size(struct errorlog *elog_data);
+int create_pel_log(struct errorlog *elog_data, char *pel_buffer,
+ size_t pel_buffer_size);
+
+#endif