cper.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  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. #include <linux/kernel.h>
  27. #include <linux/module.h>
  28. #include <linux/time.h>
  29. #include <linux/cper.h>
  30. #include <linux/acpi.h>
  31. /*
  32. * CPER record ID need to be unique even after reboot, because record
  33. * ID is used as index for ERST storage, while CPER records from
  34. * multiple boot may co-exist in ERST.
  35. */
  36. u64 cper_next_record_id(void)
  37. {
  38. static atomic64_t seq;
  39. if (!atomic64_read(&seq))
  40. atomic64_set(&seq, ((u64)get_seconds()) << 32);
  41. return atomic64_inc_return(&seq);
  42. }
  43. EXPORT_SYMBOL_GPL(cper_next_record_id);
  44. int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus)
  45. {
  46. if (estatus->data_length &&
  47. estatus->data_length < sizeof(struct acpi_hest_generic_data))
  48. return -EINVAL;
  49. if (estatus->raw_data_length &&
  50. estatus->raw_data_offset < sizeof(*estatus) + estatus->data_length)
  51. return -EINVAL;
  52. return 0;
  53. }
  54. EXPORT_SYMBOL_GPL(apei_estatus_check_header);
  55. int apei_estatus_check(const struct acpi_hest_generic_status *estatus)
  56. {
  57. struct acpi_hest_generic_data *gdata;
  58. unsigned int data_len, gedata_len;
  59. int rc;
  60. rc = apei_estatus_check_header(estatus);
  61. if (rc)
  62. return rc;
  63. data_len = estatus->data_length;
  64. gdata = (struct acpi_hest_generic_data *)(estatus + 1);
  65. while (data_len > sizeof(*gdata)) {
  66. gedata_len = gdata->error_data_length;
  67. if (gedata_len > data_len - sizeof(*gdata))
  68. return -EINVAL;
  69. data_len -= gedata_len + sizeof(*gdata);
  70. }
  71. if (data_len)
  72. return -EINVAL;
  73. return 0;
  74. }
  75. EXPORT_SYMBOL_GPL(apei_estatus_check);