1100411Speter/* 2100411Speter * Copyright (c) 2002 Marcel Moolenaar 3100411Speter * All rights reserved. 4100411Speter * 5100411Speter * Redistribution and use in source and binary forms, with or without 6100411Speter * modification, are permitted provided that the following conditions 7100411Speter * are met: 8100411Speter * 9100411Speter * 1. Redistributions of source code must retain the above copyright 10100411Speter * notice, this list of conditions and the following disclaimer. 11100411Speter * 2. Redistributions in binary form must reproduce the above copyright 12100411Speter * notice, this list of conditions and the following disclaimer in the 13100411Speter * documentation and/or other materials provided with the distribution. 14100411Speter * 15100411Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16100411Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17100411Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18100411Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19100411Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20100411Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21100411Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22100411Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23100411Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24100411Speter * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25100411Speter */ 26100411Speter 27100411Speter#include <sys/cdefs.h> 28100411Speter__FBSDID("$FreeBSD$"); 29100411Speter 30100411Speter#include <sys/types.h> 31100411Speter#include <sys/mman.h> 32100411Speter#include <sys/sysctl.h> 33100411Speter#include <sys/uuid.h> 34100411Speter 35100411Speter/* 36100411Speter * Hack to make this compile on non-ia64 machines. 37100411Speter */ 38100411Speter#ifdef __ia64__ 39100411Speter#include <machine/mca.h> 40100411Speter#else 41100411Speter#include "../../sys/ia64/include/mca.h" 42100411Speter#endif 43100411Speter 44100411Speter#include <err.h> 45100411Speter#include <errno.h> 46100411Speter#include <fcntl.h> 47105309Smarcel#include <stdarg.h> 48100411Speter#include <stdio.h> 49100411Speter#include <stdlib.h> 50100411Speter#include <string.h> 51100411Speter#include <unistd.h> 52106284Smarcel#include <uuid.h> 53100411Speter 54100411Speter#define BCD(x) ((x >> 4) * 10 + (x & 15)) 55100411Speter 56206571Smarcel#define HW_MCA_MAX_CPUID 255 57206571Smarcel 58236355Seadlerstatic const char hw_mca_count[] = "hw.mca.count"; 59236355Seadlerstatic const char hw_mca_first[] = "hw.mca.first"; 60236355Seadlerstatic const char hw_mca_last[] = "hw.mca.last"; 61236355Seadlerstatic const char hw_mca_recid[] = "hw.mca.%d.%u"; 62100411Speter 63100411Speterstatic char default_dumpfile[] = "/var/log/mca.log"; 64100411Speter 65100411Speterint fl_dump; 66100411Speterchar *file; 67100411Speter 68100411Speterstatic const char * 69100411Speterseverity(int error) 70100411Speter{ 71100411Speter 72100411Speter switch (error) { 73100411Speter case MCA_RH_ERROR_RECOVERABLE: 74100411Speter return ("recoverable"); 75100411Speter case MCA_RH_ERROR_FATAL: 76100411Speter return ("fatal"); 77100411Speter case MCA_RH_ERROR_CORRECTED: 78100411Speter return ("corrected"); 79100411Speter } 80100411Speter 81100411Speter return ("unknown"); 82100411Speter} 83100411Speter 84100411Speterstatic const char * 85106284Smarceluuid(uuid_t *id) 86100411Speter{ 87100411Speter static char buffer[64]; 88106284Smarcel char *s; 89100411Speter 90106284Smarcel uuid_to_string(id, &s, NULL); 91106284Smarcel strcpy(buffer, s); 92106284Smarcel free(s); 93100411Speter return (buffer); 94100411Speter} 95100411Speter 96105309Smarcelstatic int 97105309Smarcelshow_value(int indent, const char *var, const char *fmt, ...) 98105309Smarcel{ 99105309Smarcel va_list ap; 100105309Smarcel int len; 101105309Smarcel 102105309Smarcel len = indent; 103105309Smarcel while (indent--) 104105309Smarcel putchar(' '); 105105309Smarcel len += printf("<%s>", var); 106105309Smarcel va_start(ap, fmt); 107105309Smarcel len += vprintf(fmt, ap); 108105309Smarcel len += printf("</%s>\n", var); 109105309Smarcel return (len); 110105309Smarcel} 111105309Smarcel 112100411Speterstatic size_t 113100411Spetershow_header(struct mca_record_header *rh) 114100411Speter{ 115100411Speter 116100411Speter printf(" <header>\n"); 117105309Smarcel show_value(4, "seqnr", "%lld", (long long)rh->rh_seqnr); 118105309Smarcel show_value(4, "revision", "%d.%d", BCD(rh->rh_major), 119105309Smarcel BCD(rh->rh_minor)); 120105309Smarcel show_value(4, "severity", "%s", severity(rh->rh_error)); 121105309Smarcel show_value(4, "length", "%lld", (long long)rh->rh_length); 122105309Smarcel show_value(4, "date", "%d%02d/%02d/%02d", 123100411Speter BCD(rh->rh_time[MCA_RH_TIME_CENT]), 124100411Speter BCD(rh->rh_time[MCA_RH_TIME_YEAR]), 125100411Speter BCD(rh->rh_time[MCA_RH_TIME_MON]), 126100411Speter BCD(rh->rh_time[MCA_RH_TIME_MDAY])); 127105309Smarcel show_value(4, "time", "%02d:%02d:%02d", 128100411Speter BCD(rh->rh_time[MCA_RH_TIME_HOUR]), 129100411Speter BCD(rh->rh_time[MCA_RH_TIME_MIN]), 130100411Speter BCD(rh->rh_time[MCA_RH_TIME_SEC])); 131100411Speter if (rh->rh_flags & MCA_RH_FLAGS_PLATFORM_ID) 132105309Smarcel show_value(4, "platform", "%s", uuid(&rh->rh_platform)); 133100411Speter printf(" </header>\n"); 134100411Speter return (rh->rh_length); 135100411Speter} 136100411Speter 137100411Speterstatic void 138100411Spetershow_cpu_mod(const char *what, int idx, struct mca_cpu_mod *cpu_mod) 139100411Speter{ 140100411Speter printf(" <%s-%d>\n", what, idx); 141100411Speter if (cpu_mod->cpu_mod_flags & MCA_CPU_MOD_FLAGS_INFO) 142105309Smarcel show_value(8, "info", "0x%016llx", 143100411Speter (long long)cpu_mod->cpu_mod_info); 144100411Speter if (cpu_mod->cpu_mod_flags & MCA_CPU_MOD_FLAGS_REQID) 145105309Smarcel show_value(8, "requester", "0x%016llx", 146100411Speter (long long)cpu_mod->cpu_mod_reqid); 147100411Speter if (cpu_mod->cpu_mod_flags & MCA_CPU_MOD_FLAGS_RSPID) 148105309Smarcel show_value(8, "responder", "0x%016llx", 149100411Speter (long long)cpu_mod->cpu_mod_rspid); 150100411Speter if (cpu_mod->cpu_mod_flags & MCA_CPU_MOD_FLAGS_TGTID) 151105309Smarcel show_value(8, "target", "0x%016llx", 152100411Speter (long long)cpu_mod->cpu_mod_tgtid); 153100411Speter if (cpu_mod->cpu_mod_flags & MCA_CPU_MOD_FLAGS_IP) 154105309Smarcel show_value(8, "ip", "0x%016llx", 155100411Speter (long long)cpu_mod->cpu_mod_ip); 156100411Speter printf(" </%s-%d>\n", what, idx); 157100411Speter} 158100411Speter 159100411Speterstatic void 160100411Spetershow_cpu(struct mca_cpu_record *cpu) 161100411Speter{ 162105309Smarcel char var[16]; 163100411Speter struct mca_cpu_mod *mod; 164100411Speter struct mca_cpu_cpuid *cpuid; 165236355Seadler#ifdef notyet 166100411Speter struct mca_cpu_psi *psi; 167236355Seadler#endif 168100411Speter int i, n; 169100411Speter 170100411Speter printf(" <cpu>\n"); 171100411Speter 172100411Speter if (cpu->cpu_flags & MCA_CPU_FLAGS_ERRMAP) 173105309Smarcel show_value(6, "errmap", "0x%016llx", 174105309Smarcel (long long)cpu->cpu_errmap); 175100411Speter if (cpu->cpu_flags & MCA_CPU_FLAGS_STATE) 176105309Smarcel show_value(6, "state", "0x%016llx", 177105309Smarcel (long long)cpu->cpu_state); 178100411Speter if (cpu->cpu_flags & MCA_CPU_FLAGS_CR_LID) 179105309Smarcel show_value(6, "cr_lid", "0x%016llx", 180105309Smarcel (long long)cpu->cpu_cr_lid); 181100411Speter 182100411Speter mod = (struct mca_cpu_mod*)(cpu + 1); 183100411Speter n = MCA_CPU_FLAGS_CACHE(cpu->cpu_flags); 184100411Speter for (i = 0; i < n; i++) 185100411Speter show_cpu_mod("cache", i, mod++); 186100411Speter n = MCA_CPU_FLAGS_TLB(cpu->cpu_flags); 187100411Speter for (i = 0; i < n; i++) 188100411Speter show_cpu_mod("tlb", i, mod++); 189100411Speter n = MCA_CPU_FLAGS_BUS(cpu->cpu_flags); 190100411Speter for (i = 0; i < n; i++) 191100411Speter show_cpu_mod("bus", i, mod++); 192100411Speter n = MCA_CPU_FLAGS_REG(cpu->cpu_flags); 193100411Speter for (i = 0; i < n; i++) 194100411Speter show_cpu_mod("reg", i, mod++); 195100411Speter n = MCA_CPU_FLAGS_MS(cpu->cpu_flags); 196100411Speter for (i = 0; i < n; i++) 197100411Speter show_cpu_mod("ms", i, mod++); 198100411Speter 199100411Speter cpuid = (struct mca_cpu_cpuid*)mod; 200105309Smarcel for (i = 0; i < 6; i++) { 201105309Smarcel sprintf(var, "cpuid-%d", i); 202105309Smarcel show_value(6, var, "0x%016llx", (long long)cpuid->cpuid[i]); 203105309Smarcel } 204100411Speter 205236355Seadler#ifdef notyet 206236355Seadler psi = (struct mca_cpu_psi*)(cpuid + 1); 207236355Seadler#endif 208236355Seadler /* TODO: Dump PSI */ 209100411Speter 210100411Speter printf(" </cpu>\n"); 211100411Speter} 212100411Speter 213100411Speterstatic void 214100411Spetershow_memory(struct mca_mem_record *mem) 215100411Speter{ 216100411Speter printf(" <memory>\n"); 217100411Speter 218100411Speter if (mem->mem_flags & MCA_MEM_FLAGS_STATUS) 219105309Smarcel show_value(6, "status", "0x%016llx", 220105309Smarcel (long long)mem->mem_status); 221100411Speter if (mem->mem_flags & MCA_MEM_FLAGS_ADDR) 222105309Smarcel show_value(6, "address", "0x%016llx", 223105309Smarcel (long long)mem->mem_addr); 224100411Speter if (mem->mem_flags & MCA_MEM_FLAGS_ADDRMASK) 225105309Smarcel show_value(6, "mask", "0x%016llx", 226105309Smarcel (long long)mem->mem_addrmask); 227100411Speter if (mem->mem_flags & MCA_MEM_FLAGS_NODE) 228105309Smarcel show_value(6, "node", "0x%04x", mem->mem_node); 229100411Speter if (mem->mem_flags & MCA_MEM_FLAGS_CARD) 230105309Smarcel show_value(6, "card", "0x%04x", mem->mem_card); 231100411Speter if (mem->mem_flags & MCA_MEM_FLAGS_MODULE) 232105309Smarcel show_value(6, "module", "0x%04x", mem->mem_module); 233100411Speter if (mem->mem_flags & MCA_MEM_FLAGS_BANK) 234105309Smarcel show_value(6, "bank", "0x%04x", mem->mem_bank); 235100411Speter if (mem->mem_flags & MCA_MEM_FLAGS_DEVICE) 236105309Smarcel show_value(6, "device", "0x%04x", mem->mem_device); 237100411Speter if (mem->mem_flags & MCA_MEM_FLAGS_ROW) 238105309Smarcel show_value(6, "row", "0x%04x", mem->mem_row); 239100411Speter if (mem->mem_flags & MCA_MEM_FLAGS_COLUMN) 240105309Smarcel show_value(6, "column", "0x%04x", mem->mem_column); 241100411Speter if (mem->mem_flags & MCA_MEM_FLAGS_BITPOS) 242105309Smarcel show_value(6, "bit", "0x%04x", mem->mem_bitpos); 243100411Speter if (mem->mem_flags & MCA_MEM_FLAGS_REQID) 244105309Smarcel show_value(6, "requester", "0x%016llx", 245100411Speter (long long)mem->mem_reqid); 246100411Speter if (mem->mem_flags & MCA_MEM_FLAGS_RSPID) 247105309Smarcel show_value(6, "responder", "0x%016llx", 248100411Speter (long long)mem->mem_rspid); 249100411Speter if (mem->mem_flags & MCA_MEM_FLAGS_TGTID) 250105309Smarcel show_value(6, "target", "0x%016llx", 251100411Speter (long long)mem->mem_tgtid); 252100411Speter if (mem->mem_flags & MCA_MEM_FLAGS_BUSDATA) 253105309Smarcel show_value(6, "status", "0x%016llx", 254100411Speter (long long)mem->mem_busdata); 255100411Speter if (mem->mem_flags & MCA_MEM_FLAGS_OEM_ID) 256105309Smarcel show_value(6, "oem", "%s", uuid(&mem->mem_oem_id)); 257100411Speter /* TODO: Dump OEM data */ 258100411Speter 259100411Speter printf(" </memory>\n"); 260100411Speter} 261100411Speter 262100411Speterstatic void 263100411Spetershow_sel(void) 264100411Speter{ 265100411Speter printf(" # SEL\n"); 266100411Speter} 267100411Speter 268100411Speterstatic void 269100411Spetershow_pci_bus(struct mca_pcibus_record *pcibus) 270100411Speter{ 271100411Speter printf(" <pci-bus>\n"); 272100411Speter 273100411Speter if (pcibus->pcibus_flags & MCA_PCIBUS_FLAGS_STATUS) 274105309Smarcel show_value(6, "status", "0x%016llx", 275100411Speter (long long)pcibus->pcibus_status); 276100411Speter if (pcibus->pcibus_flags & MCA_PCIBUS_FLAGS_ERROR) 277105309Smarcel show_value(6, "error", "0x%04x", pcibus->pcibus_error); 278100411Speter if (pcibus->pcibus_flags & MCA_PCIBUS_FLAGS_BUS) 279105309Smarcel show_value(6, "bus", "0x%04x", pcibus->pcibus_bus); 280100411Speter if (pcibus->pcibus_flags & MCA_PCIBUS_FLAGS_ADDR) 281105309Smarcel show_value(6, "address", "0x%016llx", 282100411Speter (long long)pcibus->pcibus_addr); 283100411Speter if (pcibus->pcibus_flags & MCA_PCIBUS_FLAGS_DATA) 284105309Smarcel show_value(6, "data", "0x%016llx", 285100411Speter (long long)pcibus->pcibus_data); 286100411Speter if (pcibus->pcibus_flags & MCA_PCIBUS_FLAGS_CMD) 287105309Smarcel show_value(6, "cmd", "0x%016llx", 288100411Speter (long long)pcibus->pcibus_cmd); 289100411Speter if (pcibus->pcibus_flags & MCA_PCIBUS_FLAGS_REQID) 290105309Smarcel show_value(6, "requester", "0x%016llx", 291100411Speter (long long)pcibus->pcibus_reqid); 292100411Speter if (pcibus->pcibus_flags & MCA_PCIBUS_FLAGS_RSPID) 293105309Smarcel show_value(6, "responder", "0x%016llx", 294100411Speter (long long)pcibus->pcibus_rspid); 295100411Speter if (pcibus->pcibus_flags & MCA_PCIBUS_FLAGS_TGTID) 296105309Smarcel show_value(6, "target", "0x%016llx", 297100411Speter (long long)pcibus->pcibus_tgtid); 298100411Speter if (pcibus->pcibus_flags & MCA_PCIBUS_FLAGS_OEM_ID) 299105309Smarcel show_value(6, "oem", "%s", uuid(&pcibus->pcibus_oem_id)); 300100411Speter /* TODO: Dump OEM data */ 301100411Speter 302100411Speter printf(" </pci-bus>\n"); 303100411Speter} 304100411Speter 305100411Speterstatic void 306100411Spetershow_smbios(void) 307100411Speter{ 308100411Speter printf(" # SMBIOS\n"); 309100411Speter} 310100411Speter 311100411Speterstatic void 312100411Spetershow_pci_dev(struct mca_pcidev_record *pcidev) 313100411Speter{ 314100411Speter printf(" <pci-dev>\n"); 315100411Speter 316100411Speter if (pcidev->pcidev_flags & MCA_PCIDEV_FLAGS_STATUS) 317105309Smarcel show_value(6, "status", "0x%016llx", 318100411Speter (long long)pcidev->pcidev_status); 319100411Speter if (pcidev->pcidev_flags & MCA_PCIDEV_FLAGS_INFO) { 320105309Smarcel show_value(6, "vendor", "0x%04x", 321100411Speter pcidev->pcidev_info.info_vendor); 322105309Smarcel show_value(6, "device", "0x%04x", 323100411Speter pcidev->pcidev_info.info_device); 324105309Smarcel show_value(6, "class", "0x%06x", 325100411Speter MCA_PCIDEV_INFO_CLASS(pcidev->pcidev_info.info_ccfn)); 326105309Smarcel show_value(6, "function", "0x%02x", 327100411Speter MCA_PCIDEV_INFO_FUNCTION(pcidev->pcidev_info.info_ccfn)); 328105309Smarcel show_value(6, "slot", "0x%02x", pcidev->pcidev_info.info_slot); 329105309Smarcel show_value(6, "bus", "0x%04x", pcidev->pcidev_info.info_bus); 330105309Smarcel show_value(6, "segment", "0x%04x", 331100411Speter pcidev->pcidev_info.info_segment); 332100411Speter } 333100411Speter /* TODO: dump registers */ 334100411Speter /* TODO: Dump OEM data */ 335100411Speter 336100411Speter printf(" </pci-dev>\n"); 337100411Speter} 338100411Speter 339100411Speterstatic void 340100411Spetershow_generic(void) 341100411Speter{ 342100411Speter printf(" # GENERIC\n"); 343100411Speter} 344100411Speter 345100411Speterstatic size_t 346100411Spetershow_section(struct mca_section_header *sh) 347100411Speter{ 348106284Smarcel static uuid_t uuid_cpu = MCA_UUID_CPU; 349106284Smarcel static uuid_t uuid_memory = MCA_UUID_MEMORY; 350106284Smarcel static uuid_t uuid_sel = MCA_UUID_SEL; 351106284Smarcel static uuid_t uuid_pci_bus = MCA_UUID_PCI_BUS; 352106284Smarcel static uuid_t uuid_smbios = MCA_UUID_SMBIOS; 353106284Smarcel static uuid_t uuid_pci_dev = MCA_UUID_PCI_DEV; 354106284Smarcel static uuid_t uuid_generic = MCA_UUID_GENERIC; 355100411Speter 356100411Speter printf(" <section>\n"); 357105309Smarcel show_value(4, "uuid", "%s", uuid(&sh->sh_uuid)); 358105309Smarcel show_value(4, "revision", "%d.%d", BCD(sh->sh_major), 359105309Smarcel BCD(sh->sh_minor)); 360100411Speter 361106284Smarcel if (uuid_equal(&sh->sh_uuid, &uuid_cpu, NULL)) 362100411Speter show_cpu((void*)(sh + 1)); 363106284Smarcel else if (uuid_equal(&sh->sh_uuid, &uuid_memory, NULL)) 364100411Speter show_memory((void*)(sh + 1)); 365106284Smarcel else if (uuid_equal(&sh->sh_uuid, &uuid_sel, NULL)) 366100411Speter show_sel(); 367106284Smarcel else if (uuid_equal(&sh->sh_uuid, &uuid_pci_bus, NULL)) 368100411Speter show_pci_bus((void*)(sh + 1)); 369106284Smarcel else if (uuid_equal(&sh->sh_uuid, &uuid_smbios, NULL)) 370100411Speter show_smbios(); 371106284Smarcel else if (uuid_equal(&sh->sh_uuid, &uuid_pci_dev, NULL)) 372100411Speter show_pci_dev((void*)(sh + 1)); 373106284Smarcel else if (uuid_equal(&sh->sh_uuid, &uuid_generic, NULL)) 374100411Speter show_generic(); 375100411Speter 376100411Speter printf(" </section>\n"); 377100411Speter return (sh->sh_length); 378100411Speter} 379100411Speter 380100411Speterstatic void 381206571Smarcelshow(char *data, const char *mib) 382100411Speter{ 383100411Speter size_t reclen, seclen; 384100411Speter 385206571Smarcel if (mib != NULL) 386206571Smarcel printf("<!-- MIB: %s -->\n", mib); 387206571Smarcel 388100411Speter printf("<record>\n"); 389100411Speter reclen = show_header((void*)data) - sizeof(struct mca_record_header); 390100411Speter data += sizeof(struct mca_record_header); 391100411Speter while (reclen > sizeof(struct mca_section_header)) { 392100411Speter seclen = show_section((void*)data); 393100411Speter reclen -= seclen; 394100411Speter data += seclen; 395100411Speter } 396100411Speter printf("</record>\n"); 397100411Speter} 398100411Speter 399100411Speterstatic void 400100411Spetershowall(char *buf, size_t buflen) 401100411Speter{ 402100411Speter struct mca_record_header *rh; 403100411Speter size_t reclen; 404100411Speter 405100411Speter do { 406100411Speter if (buflen < sizeof(struct mca_record_header)) 407100411Speter return; 408100411Speter 409100411Speter rh = (void*)buf; 410100411Speter reclen = rh->rh_length; 411100411Speter if (buflen < reclen) 412100411Speter return; 413100411Speter 414206571Smarcel show(buf, NULL); 415100411Speter 416100411Speter buf += reclen; 417100411Speter buflen -= reclen; 418100411Speter } 419100411Speter while (1); 420100411Speter} 421100411Speter 422100411Speterstatic void 423100411Speterdump(char *data) 424100411Speter{ 425100411Speter struct mca_record_header *rh; 426100411Speter const char *fn; 427100411Speter int fd; 428100411Speter 429100411Speter rh = (void*)data; 430100411Speter fn = (file) ? file : default_dumpfile; 431100411Speter fd = open(fn, O_WRONLY|O_CREAT|O_APPEND, 0660); 432100411Speter if (fd == -1) 433100411Speter err(2, "open(%s)", fn); 434100411Speter if (write(fd, (void*)rh, rh->rh_length) == -1) 435100411Speter err(2, "write(%s)", fn); 436100411Speter close(fd); 437100411Speter} 438100411Speter 439100411Speterstatic void 440100411Speterusage(void) 441100411Speter{ 442100411Speter 443100411Speter fprintf(stderr, "usage: mca [-df]\n"); 444100411Speter exit (1); 445100411Speter} 446100411Speter 447100411Speterint 448100411Spetermain(int argc, char **argv) 449100411Speter{ 450100411Speter char mib[32]; 451100411Speter char *buf; 452100411Speter size_t len; 453100411Speter int ch, error, fd; 454206571Smarcel int count, first, last, cpuid; 455100411Speter 456100411Speter while ((ch = getopt(argc, argv, "df:")) != -1) { 457100411Speter switch(ch) { 458100411Speter case 'd': /* dump */ 459100411Speter fl_dump = 1; 460100411Speter break; 461100411Speter case 'f': 462100411Speter if (file) 463100411Speter free(file); /* XXX complain! */ 464100411Speter file = strdup(optarg); 465100411Speter break; 466100411Speter default: 467100411Speter usage(); 468100411Speter } 469100411Speter } 470100411Speter 471100411Speter argc -= optind; 472100411Speter argv += optind; 473100411Speter 474100411Speter if (file == NULL || fl_dump) { 475100411Speter len = sizeof(count); 476209677Smarcel if (sysctlbyname(hw_mca_count, &count, &len, NULL, 0) == -1) 477100411Speter err(1, hw_mca_count); 478100411Speter 479100411Speter if (count == 0) 480100411Speter errx(0, "no error records found"); 481100411Speter 482100411Speter len = sizeof(first); 483209677Smarcel if (sysctlbyname(hw_mca_first, &first, &len, NULL, 0) == -1) 484100411Speter err(1, hw_mca_first); 485100411Speter 486100411Speter len = sizeof(last); 487209677Smarcel if (sysctlbyname(hw_mca_last, &last, &len, NULL, 0) == -1) 488100411Speter err(1, hw_mca_last); 489100411Speter 490206571Smarcel cpuid = 0; 491209677Smarcel error = 0; 492100411Speter while (count && first <= last) { 493206571Smarcel do { 494206571Smarcel sprintf(mib, hw_mca_recid, first, cpuid); 495206571Smarcel len = 0; 496209677Smarcel ch = sysctlbyname(mib, NULL, &len, NULL, 0); 497209677Smarcel error = (ch == -1) ? errno : 0; 498206571Smarcel if (error != ENOENT) 499206571Smarcel break; 500206571Smarcel cpuid++; 501206571Smarcel } while (cpuid <= HW_MCA_MAX_CPUID); 502206571Smarcel if (error == ENOENT && cpuid > HW_MCA_MAX_CPUID) { 503100411Speter first++; 504206571Smarcel cpuid = 0; 505100411Speter continue; 506100411Speter } 507100411Speter if (error) 508209677Smarcel errc(1, error, "%s(1)", mib); 509100411Speter 510100411Speter buf = malloc(len); 511100411Speter if (buf == NULL) 512100411Speter err(1, "buffer"); 513100411Speter 514209677Smarcel if (sysctlbyname(mib, buf, &len, NULL, 0) == -1) 515100411Speter err(1, "%s(2)", mib); 516100411Speter 517100411Speter if (fl_dump) 518100411Speter dump(buf); 519100411Speter else 520206571Smarcel show(buf, mib); 521100411Speter 522100411Speter free(buf); 523100411Speter count--; 524206571Smarcel if (cpuid == HW_MCA_MAX_CPUID) { 525206571Smarcel first++; 526206571Smarcel cpuid = 0; 527206571Smarcel } else 528206571Smarcel cpuid++; 529100411Speter } 530100411Speter } else { 531100411Speter fd = open(file, O_RDONLY); 532100411Speter if (fd == -1) 533100411Speter err(1, "open(%s)", file); 534100411Speter 535100411Speter len = lseek(fd, 0LL, SEEK_END); 536100411Speter buf = mmap(NULL, len, PROT_READ, 0U, fd, 0LL); 537100411Speter if (buf == MAP_FAILED) 538100411Speter err(1, "mmap(%s)", file); 539100411Speter 540100411Speter showall(buf, len); 541100411Speter 542100411Speter munmap(buf, len); 543100411Speter close(fd); 544100411Speter } 545100411Speter 546100411Speter return (0); 547100411Speter} 548