Skip to content

Commit 06d65de

Browse files
yhuang-intellenb
authored andcommitted
ACPI, APEI, UEFI Common Platform Error Record (CPER) header
CPER stands for Common Platform Error Record, it is the hardware error record format used to describe platform hardware error by various APEI tables, such as ERST, BERT and HEST etc. For more information about CPER, please refer to Appendix N of UEFI Specification version 2.3. This patch mainly includes the data structure difinition header file used by other files. Signed-off-by: Huang Ying <[email protected]> Signed-off-by: Andi Kleen <[email protected]> Signed-off-by: Len Brown <[email protected]>
1 parent fab1c23 commit 06d65de

File tree

4 files changed

+418
-1
lines changed

4 files changed

+418
-1
lines changed

drivers/acpi/apei/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
obj-$(CONFIG_ACPI_APEI) += apei.o
22
obj-$(CONFIG_ACPI_APEI_EINJ) += einj.o
33

4-
apei-y := apei-base.o hest.o
4+
apei-y := apei-base.o hest.o cper.o

drivers/acpi/apei/apei-internal.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#ifndef APEI_INTERNAL_H
77
#define APEI_INTERNAL_H
88

9+
#include <linux/cper.h>
10+
911
struct apei_exec_context;
1012

1113
typedef int (*apei_exec_ins_func_t)(struct apei_exec_context *ctx,
@@ -92,4 +94,21 @@ int apei_exec_collect_resources(struct apei_exec_context *ctx,
9294

9395
struct dentry;
9496
struct dentry *apei_get_debugfs_dir(void);
97+
98+
#define apei_estatus_for_each_section(estatus, section) \
99+
for (section = (struct acpi_hest_generic_data *)(estatus + 1); \
100+
(void *)section - (void *)estatus < estatus->data_length; \
101+
section = (void *)(section+1) + section->error_data_length)
102+
103+
static inline u32 apei_estatus_len(struct acpi_hest_generic_status *estatus)
104+
{
105+
if (estatus->raw_data_length)
106+
return estatus->raw_data_offset + \
107+
estatus->raw_data_length;
108+
else
109+
return sizeof(*estatus) + estatus->data_length;
110+
}
111+
112+
int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus);
113+
int apei_estatus_check(const struct acpi_hest_generic_status *estatus);
95114
#endif

drivers/acpi/apei/cper.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* UEFI Common Platform Error Record (CPER) support
3+
*
4+
* Copyright (C) 2010, Intel Corp.
5+
* Author: Huang Ying <[email protected]>
6+
*
7+
* CPER is the format used to describe platform hardware error by
8+
* various APEI tables, such as ERST, BERT and HEST etc.
9+
*
10+
* For more information about CPER, please refer to Appendix N of UEFI
11+
* Specification version 2.3.
12+
*
13+
* This program is free software; you can redistribute it and/or
14+
* modify it under the terms of the GNU General Public License version
15+
* 2 as published by the Free Software Foundation.
16+
*
17+
* This program is distributed in the hope that it will be useful,
18+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
* GNU General Public License for more details.
21+
*
22+
* You should have received a copy of the GNU General Public License
23+
* along with this program; if not, write to the Free Software
24+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25+
*/
26+
27+
#include <linux/kernel.h>
28+
#include <linux/module.h>
29+
#include <linux/time.h>
30+
#include <linux/cper.h>
31+
#include <linux/acpi.h>
32+
33+
/*
34+
* CPER record ID need to be unique even after reboot, because record
35+
* ID is used as index for ERST storage, while CPER records from
36+
* multiple boot may co-exist in ERST.
37+
*/
38+
u64 cper_next_record_id(void)
39+
{
40+
static atomic64_t seq;
41+
42+
if (!atomic64_read(&seq))
43+
atomic64_set(&seq, ((u64)get_seconds()) << 32);
44+
45+
return atomic64_inc_return(&seq);
46+
}
47+
EXPORT_SYMBOL_GPL(cper_next_record_id);
48+
49+
int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus)
50+
{
51+
if (estatus->data_length &&
52+
estatus->data_length < sizeof(struct acpi_hest_generic_data))
53+
return -EINVAL;
54+
if (estatus->raw_data_length &&
55+
estatus->raw_data_offset < sizeof(*estatus) + estatus->data_length)
56+
return -EINVAL;
57+
58+
return 0;
59+
}
60+
EXPORT_SYMBOL_GPL(apei_estatus_check_header);
61+
62+
int apei_estatus_check(const struct acpi_hest_generic_status *estatus)
63+
{
64+
struct acpi_hest_generic_data *gdata;
65+
unsigned int data_len, gedata_len;
66+
int rc;
67+
68+
rc = apei_estatus_check_header(estatus);
69+
if (rc)
70+
return rc;
71+
data_len = estatus->data_length;
72+
gdata = (struct acpi_hest_generic_data *)(estatus + 1);
73+
while (data_len > sizeof(*gdata)) {
74+
gedata_len = gdata->error_data_length;
75+
if (gedata_len > data_len - sizeof(*gdata))
76+
return -EINVAL;
77+
data_len -= gedata_len + sizeof(*gdata);
78+
}
79+
if (data_len)
80+
return -EINVAL;
81+
82+
return 0;
83+
}
84+
EXPORT_SYMBOL_GPL(apei_estatus_check);

0 commit comments

Comments
 (0)