int apei_write_mce(struct mce *m) { struct cper_mce_record rcd; if (!m) return -EINVAL; memset(&rcd, 0, sizeof(rcd)); memcpy(rcd.hdr.signature, CPER_SIG_RECORD, CPER_SIG_SIZE); rcd.hdr.revision = CPER_RECORD_REV; rcd.hdr.signature_end = CPER_SIG_END; rcd.hdr.section_count = 1; rcd.hdr.error_severity = CPER_SER_FATAL; /* timestamp, platform_id, partition_id are all invalid */ rcd.hdr.validation_bits = 0; rcd.hdr.record_length = sizeof(rcd); rcd.hdr.creator_id = CPER_CREATOR_MCE; rcd.hdr.notification_type = CPER_NOTIFY_MCE; rcd.hdr.record_id = cper_next_record_id(); rcd.hdr.flags = CPER_HW_ERROR_FLAGS_PREVERR; rcd.sec_hdr.section_offset = (void *)&rcd.mce - (void *)&rcd; rcd.sec_hdr.section_length = sizeof(rcd.mce); rcd.sec_hdr.revision = CPER_SEC_REV; /* fru_id and fru_text is invalid */ rcd.sec_hdr.validation_bits = 0; rcd.sec_hdr.flags = CPER_SEC_PRIMARY; rcd.sec_hdr.section_type = CPER_SECTION_TYPE_MCE; rcd.sec_hdr.section_severity = CPER_SER_FATAL; memcpy(&rcd.mce, m, sizeof(*m)); return erst_write(&rcd.hdr); }
static ssize_t erst_dbg_write(struct file *filp, const char __user *ubuf, size_t usize, loff_t *off) { int rc; struct cper_record_header *rcd; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (usize > ERST_DBG_RECORD_LEN_MAX) { pr_err(ERST_DBG_PFX "Too long record to be written\n"); return -EINVAL; } if (mutex_lock_interruptible(&erst_dbg_mutex)) return -EINTR; if (usize > erst_dbg_buf_len) { void *p; rc = -ENOMEM; p = kmalloc(usize, GFP_KERNEL); if (!p) goto out; kfree(erst_dbg_buf); erst_dbg_buf = p; erst_dbg_buf_len = usize; } rc = copy_from_user(erst_dbg_buf, ubuf, usize); if (rc) { rc = -EFAULT; goto out; } rcd = erst_dbg_buf; rc = -EINVAL; if (rcd->record_length != usize) goto out; rc = erst_write(erst_dbg_buf); out: mutex_unlock(&erst_dbg_mutex); return rc < 0 ? rc : usize; }