1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Interface for exporting the OPAL ELF core. 4 * Heavily inspired from fs/proc/vmcore.c 5 * 6 * Copyright 2019, Hari Bathini, IBM Corporation. 7 */ 8 9 #define pr_fmt(fmt) "opal core: " fmt 10 11 #include <linux/memblock.h> 12 #include <linux/uaccess.h> 13 #include <linux/proc_fs.h> 14 #include <linux/elf.h> 15 #include <linux/elfcore.h> 16 #include <linux/kobject.h> 17 #include <linux/sysfs.h> 18 #include <linux/slab.h> 19 #include <linux/crash_core.h> 20 #include <linux/of.h> 21 22 #include <asm/page.h> 23 #include <asm/opal.h> 24 #include <asm/fadump-internal.h> 25 26 #include "opal-fadump.h" 27 28 #define MAX_PT_LOAD_CNT 8 29 30 /* NT_AUXV note related info */ 31 #define AUXV_CNT 1 32 #define AUXV_DESC_SZ (((2 * AUXV_CNT) + 1) * sizeof(Elf64_Off)) 33 34 struct opalcore_config { 35 u32 num_cpus; 36 /* PIR value of crashing CPU */ 37 u32 crashing_cpu; 38 39 /* CPU state data info from F/W */ 40 u64 cpu_state_destination_vaddr; 41 u64 cpu_state_data_size; 42 u64 cpu_state_entry_size; 43 44 /* OPAL memory to be exported as PT_LOAD segments */ 45 u64 ptload_addr[MAX_PT_LOAD_CNT]; 46 u64 ptload_size[MAX_PT_LOAD_CNT]; 47 u64 ptload_cnt; 48 49 /* Pointer to the first PT_LOAD in the ELF core file */ 50 Elf64_Phdr *ptload_phdr; 51 52 /* Total size of opalcore file. */ 53 size_t opalcore_size; 54 55 /* Buffer for all the ELF core headers and the PT_NOTE */ 56 size_t opalcorebuf_sz; 57 char *opalcorebuf; 58 59 /* NT_AUXV buffer */ 60 char auxv_buf[AUXV_DESC_SZ]; 61 }; 62 63 struct opalcore { 64 struct list_head list; 65 u64 paddr; 66 size_t size; 67 loff_t offset; 68 }; 69 70 static LIST_HEAD(opalcore_list); 71 static struct opalcore_config *oc_conf; 72 static const struct opal_mpipl_fadump *opalc_metadata; 73 static const struct opal_mpipl_fadump *opalc_cpu_metadata; 74 75 /* 76 * Set crashing CPU's signal to SIGUSR1. if the kernel is triggered 77 * by kernel, SIGTERM otherwise. 78 */ 79 bool kernel_initiated; 80 81 static struct opalcore * __init get_new_element(void) 82 { 83 return kzalloc(sizeof(struct opalcore), GFP_KERNEL); 84 } 85 86 static inline int is_opalcore_usable(void) 87 { 88 return (oc_conf && oc_conf->opalcorebuf != NULL) ? 1 : 0; 89 } 90 91 static Elf64_Word *append_elf64_note(Elf64_Word *buf, char *name, 92 u32 type, void *data, 93 size_t data_len) 94 { 95 Elf64_Nhdr *note = (Elf64_Nhdr *)buf; 96 Elf64_Word namesz = strlen(name) + 1; 97 98 note->n_namesz = cpu_to_be32(namesz); 99 note->n_descsz = cpu_to_be32(data_len); 100 note->n_type = cpu_to_be32(type); 101 buf += DIV_ROUND_UP(sizeof(*note), sizeof(Elf64_Word)); 102 memcpy(buf, name, namesz); 103 buf += DIV_ROUND_UP(namesz, sizeof(Elf64_Word)); 104 memcpy(buf, data, data_len); 105 buf += DIV_ROUND_UP(data_len, sizeof(Elf64_Word)); 106 107 return buf; 108 } 109 110 static void fill_prstatus(struct elf_prstatus *prstatus, int pir, 111 struct pt_regs *regs) 112 { 113 memset(prstatus, 0, sizeof(struct elf_prstatus)); 114 elf_core_copy_kernel_regs(&(prstatus->pr_reg), regs); 115 116 /* 117 * Overload PID with PIR value. 118 * As a PIR value could also be '0', add an offset of '100' 119 * to every PIR to avoid misinterpretations in GDB. 120 */ 121 prstatus->pr_pid = cpu_to_be32(100 + pir); 122 prstatus->pr_ppid = cpu_to_be32(1); 123 124 /* 125 * Indicate SIGUSR1 for crash initiated from kernel. 126 * SIGTERM otherwise. 127 */ 128 if (pir == oc_conf->crashing_cpu) { 129 short sig; 130 131 sig = kernel_initiated ? SIGUSR1 : SIGTERM; 132 prstatus->pr_cursig = cpu_to_be16(sig); 133 } 134 } 135 136 static Elf64_Word *auxv_to_elf64_notes(Elf64_Word *buf, 137 u64 opal_boot_entry) 138 { 139 Elf64_Off *bufp = (Elf64_Off *)oc_conf->auxv_buf; 140 int idx = 0; 141 142 memset(bufp, 0, AUXV_DESC_SZ); 143 144 /* Entry point of OPAL */ 145 bufp[idx++] = cpu_to_be64(AT_ENTRY); 146 bufp[idx++] = cpu_to_be64(opal_boot_entry); 147 148 /* end of vector */ 149 bufp[idx++] = cpu_to_be64(AT_NULL); 150 151 buf = append_elf64_note(buf, CRASH_CORE_NOTE_NAME, NT_AUXV, 152 oc_conf->auxv_buf, AUXV_DESC_SZ); 153 return buf; 154 } 155 156 /* 157 * Read from the ELF header and then the crash dump. 158 * Returns number of bytes read on success, -errno on failure. 159 */ 160 static ssize_t read_opalcore(struct file *file, struct kobject *kobj, 161 struct bin_attribute *bin_attr, char *to, 162 loff_t pos, size_t count) 163 { 164 struct opalcore *m; 165 ssize_t tsz, avail; 166 loff_t tpos = pos; 167 168 if (pos >= oc_conf->opalcore_size) 169 return 0; 170 171 /* Adjust count if it goes beyond opalcore size */ 172 avail = oc_conf->opalcore_size - pos; 173 if (count > avail) 174 count = avail; 175 176 if (count == 0) 177 return 0; 178 179 /* Read ELF core header and/or PT_NOTE segment */ 180 if (tpos < oc_conf->opalcorebuf_sz) { 181 tsz = min_t(size_t, oc_conf->opalcorebuf_sz - tpos, count); 182 memcpy(to, oc_conf->opalcorebuf + tpos, tsz); 183 to += tsz; 184 tpos += tsz; 185 count -= tsz; 186 } 187 188 list_for_each_entry(m, &opalcore_list, list) { 189 /* nothing more to read here */ 190 if (count == 0) 191 break; 192 193 if (tpos < m->offset + m->size) { 194 void *addr; 195 196 tsz = min_t(size_t, m->offset + m->size - tpos, count); 197 addr = (void *)(m->paddr + tpos - m->offset); 198 memcpy(to, __va(addr), tsz); 199 to += tsz; 200 tpos += tsz; 201 count -= tsz; 202 } 203 } 204 205 return (tpos - pos); 206 } 207 208 static struct bin_attribute opal_core_attr = { 209 .attr = {.name = "core", .mode = 0400}, 210 .read = read_opalcore 211 }; 212 213 /* 214 * Read CPU state dump data and convert it into ELF notes. 215 * 216 * Each register entry is of 16 bytes, A numerical identifier along with 217 * a GPR/SPR flag in the first 8 bytes and the register value in the next 218 * 8 bytes. For more details refer to F/W documentation. 219 */ 220 static Elf64_Word * __init opalcore_append_cpu_notes(Elf64_Word *buf) 221 { 222 u32 thread_pir, size_per_thread, regs_offset, regs_cnt, reg_esize; 223 struct hdat_fadump_thread_hdr *thdr; 224 struct elf_prstatus prstatus; 225 Elf64_Word *first_cpu_note; 226 struct pt_regs regs; 227 char *bufp; 228 int i; 229 230 size_per_thread = oc_conf->cpu_state_entry_size; 231 bufp = __va(oc_conf->cpu_state_destination_vaddr); 232 233 /* 234 * Offset for register entries, entry size and registers count is 235 * duplicated in every thread header in keeping with HDAT format. 236 * Use these values from the first thread header. 237 */ 238 thdr = (struct hdat_fadump_thread_hdr *)bufp; 239 regs_offset = (offsetof(struct hdat_fadump_thread_hdr, offset) + 240 be32_to_cpu(thdr->offset)); 241 reg_esize = be32_to_cpu(thdr->esize); 242 regs_cnt = be32_to_cpu(thdr->ecnt); 243 244 pr_debug("--------CPU State Data------------\n"); 245 pr_debug("NumCpus : %u\n", oc_conf->num_cpus); 246 pr_debug("\tOffset: %u, Entry size: %u, Cnt: %u\n", 247 regs_offset, reg_esize, regs_cnt); 248 249 /* 250 * Skip past the first CPU note. Fill this note with the 251 * crashing CPU's prstatus. 252 */ 253 first_cpu_note = buf; 254 buf = append_elf64_note(buf, CRASH_CORE_NOTE_NAME, NT_PRSTATUS, 255 &prstatus, sizeof(prstatus)); 256 257 for (i = 0; i < oc_conf->num_cpus; i++, bufp += size_per_thread) { 258 thdr = (struct hdat_fadump_thread_hdr *)bufp; 259 thread_pir = be32_to_cpu(thdr->pir); 260 261 pr_debug("[%04d] PIR: 0x%x, core state: 0x%02x\n", 262 i, thread_pir, thdr->core_state); 263 264 /* 265 * Register state data of MAX cores is provided by firmware, 266 * but some of this cores may not be active. So, while 267 * processing register state data, check core state and 268 * skip threads that belong to inactive cores. 269 */ 270 if (thdr->core_state == HDAT_FADUMP_CORE_INACTIVE) 271 continue; 272 273 opal_fadump_read_regs((bufp + regs_offset), regs_cnt, 274 reg_esize, false, ®s); 275 276 pr_debug("PIR 0x%x - R1 : 0x%llx, NIP : 0x%llx\n", thread_pir, 277 be64_to_cpu(regs.gpr[1]), be64_to_cpu(regs.nip)); 278 fill_prstatus(&prstatus, thread_pir, ®s); 279 280 if (thread_pir != oc_conf->crashing_cpu) { 281 buf = append_elf64_note(buf, CRASH_CORE_NOTE_NAME, 282 NT_PRSTATUS, &prstatus, 283 sizeof(prstatus)); 284 } else { 285 /* 286 * Add crashing CPU as the first NT_PRSTATUS note for 287 * GDB to process the core file appropriately. 288 */ 289 append_elf64_note(first_cpu_note, CRASH_CORE_NOTE_NAME, 290 NT_PRSTATUS, &prstatus, 291 sizeof(prstatus)); 292 } 293 } 294 295 return buf; 296 } 297 298 static int __init create_opalcore(void) 299 { 300 u64 opal_boot_entry, opal_base_addr, paddr; 301 u32 hdr_size, cpu_notes_size, count; 302 struct device_node *dn; 303 struct opalcore *new; 304 loff_t opalcore_off; 305 struct page *page; 306 Elf64_Phdr *phdr; 307 Elf64_Ehdr *elf; 308 int i, ret; 309 char *bufp; 310 311 /* Get size of header & CPU notes for OPAL core */ 312 hdr_size = (sizeof(Elf64_Ehdr) + 313 ((oc_conf->ptload_cnt + 1) * sizeof(Elf64_Phdr))); 314 cpu_notes_size = ((oc_conf->num_cpus * (CRASH_CORE_NOTE_HEAD_BYTES + 315 CRASH_CORE_NOTE_NAME_BYTES + 316 CRASH_CORE_NOTE_DESC_BYTES)) + 317 (CRASH_CORE_NOTE_HEAD_BYTES + 318 CRASH_CORE_NOTE_NAME_BYTES + AUXV_DESC_SZ)); 319 320 /* Allocate buffer to setup OPAL core */ 321 oc_conf->opalcorebuf_sz = PAGE_ALIGN(hdr_size + cpu_notes_size); 322 oc_conf->opalcorebuf = alloc_pages_exact(oc_conf->opalcorebuf_sz, 323 GFP_KERNEL | __GFP_ZERO); 324 if (!oc_conf->opalcorebuf) { 325 pr_err("Not enough memory to setup OPAL core (size: %lu)\n", 326 oc_conf->opalcorebuf_sz); 327 oc_conf->opalcorebuf_sz = 0; 328 return -ENOMEM; 329 } 330 count = oc_conf->opalcorebuf_sz / PAGE_SIZE; 331 page = virt_to_page(oc_conf->opalcorebuf); 332 for (i = 0; i < count; i++) 333 mark_page_reserved(page + i); 334 335 pr_debug("opalcorebuf = 0x%llx\n", (u64)oc_conf->opalcorebuf); 336 337 /* Read OPAL related device-tree entries */ 338 dn = of_find_node_by_name(NULL, "ibm,opal"); 339 if (dn) { 340 ret = of_property_read_u64(dn, "opal-base-address", 341 &opal_base_addr); 342 pr_debug("opal-base-address: %llx\n", opal_base_addr); 343 ret |= of_property_read_u64(dn, "opal-boot-address", 344 &opal_boot_entry); 345 pr_debug("opal-boot-address: %llx\n", opal_boot_entry); 346 } 347 if (!dn || ret) 348 pr_warn("WARNING: Failed to read OPAL base & entry values\n"); 349 350 /* Use count to keep track of the program headers */ 351 count = 0; 352 353 bufp = oc_conf->opalcorebuf; 354 elf = (Elf64_Ehdr *)bufp; 355 bufp += sizeof(Elf64_Ehdr); 356 memcpy(elf->e_ident, ELFMAG, SELFMAG); 357 elf->e_ident[EI_CLASS] = ELF_CLASS; 358 elf->e_ident[EI_DATA] = ELFDATA2MSB; 359 elf->e_ident[EI_VERSION] = EV_CURRENT; 360 elf->e_ident[EI_OSABI] = ELF_OSABI; 361 memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); 362 elf->e_type = cpu_to_be16(ET_CORE); 363 elf->e_machine = cpu_to_be16(ELF_ARCH); 364 elf->e_version = cpu_to_be32(EV_CURRENT); 365 elf->e_entry = 0; 366 elf->e_phoff = cpu_to_be64(sizeof(Elf64_Ehdr)); 367 elf->e_shoff = 0; 368 elf->e_flags = 0; 369 370 elf->e_ehsize = cpu_to_be16(sizeof(Elf64_Ehdr)); 371 elf->e_phentsize = cpu_to_be16(sizeof(Elf64_Phdr)); 372 elf->e_phnum = 0; 373 elf->e_shentsize = 0; 374 elf->e_shnum = 0; 375 elf->e_shstrndx = 0; 376 377 phdr = (Elf64_Phdr *)bufp; 378 bufp += sizeof(Elf64_Phdr); 379 phdr->p_type = cpu_to_be32(PT_NOTE); 380 phdr->p_flags = 0; 381 phdr->p_align = 0; 382 phdr->p_paddr = phdr->p_vaddr = 0; 383 phdr->p_offset = cpu_to_be64(hdr_size); 384 phdr->p_filesz = phdr->p_memsz = cpu_to_be64(cpu_notes_size); 385 count++; 386 387 opalcore_off = oc_conf->opalcorebuf_sz; 388 oc_conf->ptload_phdr = (Elf64_Phdr *)bufp; 389 paddr = 0; 390 for (i = 0; i < oc_conf->ptload_cnt; i++) { 391 phdr = (Elf64_Phdr *)bufp; 392 bufp += sizeof(Elf64_Phdr); 393 phdr->p_type = cpu_to_be32(PT_LOAD); 394 phdr->p_flags = cpu_to_be32(PF_R|PF_W|PF_X); 395 phdr->p_align = 0; 396 397 new = get_new_element(); 398 if (!new) 399 return -ENOMEM; 400 new->paddr = oc_conf->ptload_addr[i]; 401 new->size = oc_conf->ptload_size[i]; 402 new->offset = opalcore_off; 403 list_add_tail(&new->list, &opalcore_list); 404 405 phdr->p_paddr = cpu_to_be64(paddr); 406 phdr->p_vaddr = cpu_to_be64(opal_base_addr + paddr); 407 phdr->p_filesz = phdr->p_memsz = 408 cpu_to_be64(oc_conf->ptload_size[i]); 409 phdr->p_offset = cpu_to_be64(opalcore_off); 410 411 count++; 412 opalcore_off += oc_conf->ptload_size[i]; 413 paddr += oc_conf->ptload_size[i]; 414 } 415 416 elf->e_phnum = cpu_to_be16(count); 417 418 bufp = (char *)opalcore_append_cpu_notes((Elf64_Word *)bufp); 419 bufp = (char *)auxv_to_elf64_notes((Elf64_Word *)bufp, opal_boot_entry); 420 421 oc_conf->opalcore_size = opalcore_off; 422 return 0; 423 } 424 425 static void opalcore_cleanup(void) 426 { 427 if (oc_conf == NULL) 428 return; 429 430 /* Remove OPAL core sysfs file */ 431 sysfs_remove_bin_file(opal_kobj, &opal_core_attr); 432 oc_conf->ptload_phdr = NULL; 433 oc_conf->ptload_cnt = 0; 434 435 /* free the buffer used for setting up OPAL core */ 436 if (oc_conf->opalcorebuf) { 437 void *end = (void *)((u64)oc_conf->opalcorebuf + 438 oc_conf->opalcorebuf_sz); 439 440 free_reserved_area(oc_conf->opalcorebuf, end, -1, NULL); 441 oc_conf->opalcorebuf = NULL; 442 oc_conf->opalcorebuf_sz = 0; 443 } 444 445 kfree(oc_conf); 446 oc_conf = NULL; 447 } 448 __exitcall(opalcore_cleanup); 449 450 static void __init opalcore_config_init(void) 451 { 452 u32 idx, cpu_data_version; 453 struct device_node *np; 454 const __be32 *prop; 455 u64 addr = 0; 456 int i, ret; 457 458 np = of_find_node_by_path("/ibm,opal/dump"); 459 if (np == NULL) 460 return; 461 462 if (!of_device_is_compatible(np, "ibm,opal-dump")) { 463 pr_warn("Support missing for this f/w version!\n"); 464 return; 465 } 466 467 /* Check if dump has been initiated on last reboot */ 468 prop = of_get_property(np, "mpipl-boot", NULL); 469 if (!prop) { 470 of_node_put(np); 471 return; 472 } 473 474 /* Get OPAL metadata */ 475 ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_OPAL, &addr); 476 if ((ret != OPAL_SUCCESS) || !addr) { 477 pr_err("Failed to get OPAL metadata (%d)\n", ret); 478 goto error_out; 479 } 480 481 addr = be64_to_cpu(addr); 482 pr_debug("OPAL metadata addr: %llx\n", addr); 483 opalc_metadata = __va(addr); 484 485 /* Get OPAL CPU metadata */ 486 ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_CPU, &addr); 487 if ((ret != OPAL_SUCCESS) || !addr) { 488 pr_err("Failed to get OPAL CPU metadata (%d)\n", ret); 489 goto error_out; 490 } 491 492 addr = be64_to_cpu(addr); 493 pr_debug("CPU metadata addr: %llx\n", addr); 494 opalc_cpu_metadata = __va(addr); 495 496 /* Allocate memory for config buffer */ 497 oc_conf = kzalloc(sizeof(struct opalcore_config), GFP_KERNEL); 498 if (oc_conf == NULL) 499 goto error_out; 500 501 /* Parse OPAL metadata */ 502 if (opalc_metadata->version != OPAL_MPIPL_VERSION) { 503 pr_warn("Supported OPAL metadata version: %u, found: %u!\n", 504 OPAL_MPIPL_VERSION, opalc_metadata->version); 505 pr_warn("WARNING: F/W using newer OPAL metadata format!!\n"); 506 } 507 508 oc_conf->ptload_cnt = 0; 509 idx = be32_to_cpu(opalc_metadata->region_cnt); 510 if (idx > MAX_PT_LOAD_CNT) { 511 pr_warn("WARNING: OPAL regions count (%d) adjusted to limit (%d)", 512 MAX_PT_LOAD_CNT, idx); 513 idx = MAX_PT_LOAD_CNT; 514 } 515 for (i = 0; i < idx; i++) { 516 oc_conf->ptload_addr[oc_conf->ptload_cnt] = 517 be64_to_cpu(opalc_metadata->region[i].dest); 518 oc_conf->ptload_size[oc_conf->ptload_cnt++] = 519 be64_to_cpu(opalc_metadata->region[i].size); 520 } 521 oc_conf->ptload_cnt = i; 522 oc_conf->crashing_cpu = be32_to_cpu(opalc_metadata->crashing_pir); 523 524 if (!oc_conf->ptload_cnt) { 525 pr_err("OPAL memory regions not found\n"); 526 goto error_out; 527 } 528 529 /* Parse OPAL CPU metadata */ 530 cpu_data_version = be32_to_cpu(opalc_cpu_metadata->cpu_data_version); 531 if (cpu_data_version != HDAT_FADUMP_CPU_DATA_VER) { 532 pr_warn("Supported CPU data version: %u, found: %u!\n", 533 HDAT_FADUMP_CPU_DATA_VER, cpu_data_version); 534 pr_warn("WARNING: F/W using newer CPU state data format!!\n"); 535 } 536 537 addr = be64_to_cpu(opalc_cpu_metadata->region[0].dest); 538 if (!addr) { 539 pr_err("CPU state data not found!\n"); 540 goto error_out; 541 } 542 oc_conf->cpu_state_destination_vaddr = (u64)__va(addr); 543 544 oc_conf->cpu_state_data_size = 545 be64_to_cpu(opalc_cpu_metadata->region[0].size); 546 oc_conf->cpu_state_entry_size = 547 be32_to_cpu(opalc_cpu_metadata->cpu_data_size); 548 549 if ((oc_conf->cpu_state_entry_size == 0) || 550 (oc_conf->cpu_state_entry_size > oc_conf->cpu_state_data_size)) { 551 pr_err("CPU state data is invalid.\n"); 552 goto error_out; 553 } 554 oc_conf->num_cpus = (oc_conf->cpu_state_data_size / 555 oc_conf->cpu_state_entry_size); 556 557 of_node_put(np); 558 return; 559 560 error_out: 561 pr_err("Could not export /sys/firmware/opal/core\n"); 562 opalcore_cleanup(); 563 of_node_put(np); 564 } 565 566 static ssize_t fadump_release_opalcore_store(struct kobject *kobj, 567 struct kobj_attribute *attr, 568 const char *buf, size_t count) 569 { 570 int input = -1; 571 572 if (kstrtoint(buf, 0, &input)) 573 return -EINVAL; 574 575 if (input == 1) { 576 if (oc_conf == NULL) { 577 pr_err("'/sys/firmware/opal/core' file not accessible!\n"); 578 return -EPERM; 579 } 580 581 /* 582 * Take away '/sys/firmware/opal/core' and release all memory 583 * used for exporting this file. 584 */ 585 opalcore_cleanup(); 586 } else 587 return -EINVAL; 588 589 return count; 590 } 591 592 static struct kobj_attribute opalcore_rel_attr = __ATTR(fadump_release_opalcore, 593 0200, NULL, 594 fadump_release_opalcore_store); 595 596 static int __init opalcore_init(void) 597 { 598 int rc = -1; 599 600 opalcore_config_init(); 601 602 if (oc_conf == NULL) 603 return rc; 604 605 create_opalcore(); 606 607 /* 608 * If oc_conf->opalcorebuf= is set in the 2nd kernel, 609 * then capture the dump. 610 */ 611 if (!(is_opalcore_usable())) { 612 pr_err("Failed to export /sys/firmware/opal/core\n"); 613 opalcore_cleanup(); 614 return rc; 615 } 616 617 /* Set OPAL core file size */ 618 opal_core_attr.size = oc_conf->opalcore_size; 619 620 /* Export OPAL core sysfs file */ 621 rc = sysfs_create_bin_file(opal_kobj, &opal_core_attr); 622 if (rc != 0) { 623 pr_err("Failed to export /sys/firmware/opal/core\n"); 624 opalcore_cleanup(); 625 return rc; 626 } 627 628 rc = sysfs_create_file(kernel_kobj, &opalcore_rel_attr.attr); 629 if (rc) { 630 pr_warn("unable to create sysfs file fadump_release_opalcore (%d)\n", 631 rc); 632 } 633 634 return 0; 635 } 636 fs_initcall(opalcore_init); 637