/* * UEFI Common Platform Error Record (CPER) support * * Copyright (C) 2010, Intel Corp. * Author: Huang Ying * * CPER is the 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 program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include /* * CPER record ID need to be unique even after reboot, because record * ID is used as index for ERST storage, while CPER records from * multiple boot may co-exist in ERST. */ u64 cper_next_record_id(void) { static atomic64_t seq; if (!atomic64_read(&seq)) atomic64_set(&seq, ((u64)get_seconds()) << 32); return atomic64_inc_return(&seq); } EXPORT_SYMBOL_GPL(cper_next_record_id); int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus) { if (estatus->data_length && estatus->data_length < sizeof(struct acpi_hest_generic_data)) return -EINVAL; if (estatus->raw_data_length && estatus->raw_data_offset < sizeof(*estatus) + estatus->data_length) return -EINVAL; return 0; } EXPORT_SYMBOL_GPL(apei_estatus_check_header); int apei_estatus_check(const struct acpi_hest_generic_status *estatus) { struct acpi_hest_generic_data *gdata; unsigned int data_len, gedata_len; int rc; rc = apei_estatus_check_header(estatus); if (rc) return rc; data_len = estatus->data_length; gdata = (struct acpi_hest_generic_data *)(estatus + 1); while (data_len > sizeof(*gdata)) { gedata_len = gdata->error_data_length; if (gedata_len > data_len - sizeof(*gdata)) return -EINVAL; data_len -= gedata_len + sizeof(*gdata); } if (data_len) return -EINVAL; return 0; } EXPORT_SYMBOL_GPL(apei_estatus_check);