1/* 2 * UEFI Common Platform Error Record (CPER) support 3 * 4 * Copyright (C) 2010, Intel Corp. 5 * Author: Huang Ying <ying.huang@intel.com> 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 */ 38u64 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} 47EXPORT_SYMBOL_GPL(cper_next_record_id); 48 49int 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} 60EXPORT_SYMBOL_GPL(apei_estatus_check_header); 61 62int 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} 84EXPORT_SYMBOL_GPL(apei_estatus_check); 85