// Retrieve total free space available in SEL log int sel_free_space(void) { int total_space; int used_space; total_space = SEL_RECORDS_MAX * sizeof(sel_msg_t); used_space = sel_num_entries() * sizeof(sel_msg_t); return (total_space - used_space); }
// Add a new entry in to SEL log // IPMI/Section 31.6 int sel_add_entry(sel_msg_t *msg, int *rec_id) { // If the SEL if full, roll over. To keep track of empty condition, use // one empty location less than the max records. if (sel_num_entries() == SEL_RECORDS_MAX) { syslog(LOG_ALERT, "sel_add_entry: SEL rollover\n"); if (++g_sel_hdr.begin > SEL_INDEX_MAX) { g_sel_hdr.begin = SEL_INDEX_MIN; } } // Update message's time stamp starting at byte 4 time_stamp_fill(&msg->msg[3]); // Add the enry at end memcpy(g_sel_data[g_sel_hdr.end].msg, msg->msg, sizeof(sel_msg_t)); // Return the newly added record ID *rec_id = g_sel_hdr.end+1; if (file_store_sel_data(*rec_id, msg)) { syslog(LOG_ALERT, "sel_add_entry: file_store_sel_data\n"); return -1; } // Increment the end pointer if (++g_sel_hdr.end > SEL_INDEX_MAX) { g_sel_hdr.end = SEL_INDEX_MIN; } // Update timestamp for add in header time_stamp_fill(g_sel_hdr.ts_add.ts); // Store the structure persistently if (file_store_sel_hdr()) { syslog(LOG_ALERT, "sel_add_entry: file_store_sel_hdr\n"); return -1; } return 0; }
static void storage_get_sel_info (unsigned char *request, unsigned char *response, unsigned char *res_len) { ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; ipmi_res_t *res = (ipmi_res_t *) response; unsigned char *data = &res->data[0]; int num_entries; // number of log entries int free_space; // free space in SEL device in bytes time_stamp_t ts_recent_add; // Recent Addition Timestamp time_stamp_t ts_recent_erase; // Recent Erasure Timestamp // Use platform APIs to get SEL information num_entries = sel_num_entries (req->payload_id); free_space = sel_free_space (req->payload_id); sel_ts_recent_add (req->payload_id, &ts_recent_add); sel_ts_recent_erase (req->payload_id, &ts_recent_erase); res->cc = CC_SUCCESS; *data++ = IPMI_SEL_VERSION; // SEL version *data++ = num_entries & 0xFF; // number of log entries *data++ = (num_entries >> 8) & 0xFF; *data++ = free_space & 0xFF; // Free SEL Space *data++ = (free_space >> 8) & 0xFF; memcpy(data, ts_recent_add.ts, SIZE_TIME_STAMP); data += SIZE_TIME_STAMP; memcpy(data, ts_recent_erase.ts, SIZE_TIME_STAMP); data += SIZE_TIME_STAMP; *data++ = 0x02; // Operations supported *res_len = data - &res->data[0]; return; }
// Get the SEL entry for a given record ID // IPMI/Section 31.5 int sel_get_entry(int read_rec_id, sel_msg_t *msg, int *next_rec_id) { int index; // Find the index in to array based on given index if (read_rec_id == SEL_RECID_FIRST) { index = g_sel_hdr.begin; } else if (read_rec_id == SEL_RECID_LAST) { if (g_sel_hdr.end) { index = g_sel_hdr.end - 1; } else { index = SEL_INDEX_MAX; } } else { index = read_rec_id - 1; } // If the log is empty return error if (sel_num_entries() == 0) { syslog(LOG_ALERT, "sel_get_entry: No entries\n"); return -1; } // Check for boundary conditions if ((index < SEL_INDEX_MIN) || (index > SEL_INDEX_MAX)) { syslog(LOG_ALERT, "sel_get_entry: Invalid Record ID %d\n", read_rec_id); return -1; } // If begin < end, check to make sure the given id falls between if (g_sel_hdr.begin < g_sel_hdr.end) { if (index < g_sel_hdr.begin || index >= g_sel_hdr.end) { syslog(LOG_ALERT, "sel_get_entry: Wrong Record ID %d\n", read_rec_id); return -1; } } // If end < begin, check to make sure the given id is valid if (g_sel_hdr.begin > g_sel_hdr.end) { if (index >= g_sel_hdr.end && index < g_sel_hdr.begin) { syslog(LOG_ALERT, "sel_get_entry: Wrong Record ID2 %d\n", read_rec_id); return -1; } } memcpy(msg->msg, g_sel_data[index].msg, sizeof(sel_msg_t)); // Return the next record ID in the log *next_rec_id = read_rec_id++; if (*next_rec_id > SEL_INDEX_MAX) { *next_rec_id = SEL_INDEX_MIN; } // If this is the last entry in the log, return 0xFFFF if (*next_rec_id == g_sel_hdr.end) { *next_rec_id = SEL_RECID_LAST; } return 0; }