Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Interface for exporting the OPAL ELF core.
0004  * Heavily inspired from fs/proc/vmcore.c
0005  *
0006  * Copyright 2019, Hari Bathini, IBM Corporation.
0007  */
0008 
0009 #define pr_fmt(fmt) "opal core: " fmt
0010 
0011 #include <linux/memblock.h>
0012 #include <linux/uaccess.h>
0013 #include <linux/proc_fs.h>
0014 #include <linux/elf.h>
0015 #include <linux/elfcore.h>
0016 #include <linux/kobject.h>
0017 #include <linux/sysfs.h>
0018 #include <linux/slab.h>
0019 #include <linux/crash_core.h>
0020 #include <linux/of.h>
0021 
0022 #include <asm/page.h>
0023 #include <asm/opal.h>
0024 #include <asm/fadump-internal.h>
0025 
0026 #include "opal-fadump.h"
0027 
0028 #define MAX_PT_LOAD_CNT     8
0029 
0030 /* NT_AUXV note related info */
0031 #define AUXV_CNT        1
0032 #define AUXV_DESC_SZ        (((2 * AUXV_CNT) + 1) * sizeof(Elf64_Off))
0033 
0034 struct opalcore_config {
0035     u32         num_cpus;
0036     /* PIR value of crashing CPU */
0037     u32         crashing_cpu;
0038 
0039     /* CPU state data info from F/W */
0040     u64         cpu_state_destination_vaddr;
0041     u64         cpu_state_data_size;
0042     u64         cpu_state_entry_size;
0043 
0044     /* OPAL memory to be exported as PT_LOAD segments */
0045     u64         ptload_addr[MAX_PT_LOAD_CNT];
0046     u64         ptload_size[MAX_PT_LOAD_CNT];
0047     u64         ptload_cnt;
0048 
0049     /* Pointer to the first PT_LOAD in the ELF core file */
0050     Elf64_Phdr      *ptload_phdr;
0051 
0052     /* Total size of opalcore file. */
0053     size_t          opalcore_size;
0054 
0055     /* Buffer for all the ELF core headers and the PT_NOTE */
0056     size_t          opalcorebuf_sz;
0057     char            *opalcorebuf;
0058 
0059     /* NT_AUXV buffer */
0060     char            auxv_buf[AUXV_DESC_SZ];
0061 };
0062 
0063 struct opalcore {
0064     struct list_head    list;
0065     u64         paddr;
0066     size_t          size;
0067     loff_t          offset;
0068 };
0069 
0070 static LIST_HEAD(opalcore_list);
0071 static struct opalcore_config *oc_conf;
0072 static const struct opal_mpipl_fadump *opalc_metadata;
0073 static const struct opal_mpipl_fadump *opalc_cpu_metadata;
0074 static struct kobject *mpipl_kobj;
0075 
0076 /*
0077  * Set crashing CPU's signal to SIGUSR1. if the kernel is triggered
0078  * by kernel, SIGTERM otherwise.
0079  */
0080 bool kernel_initiated;
0081 
0082 static struct opalcore * __init get_new_element(void)
0083 {
0084     return kzalloc(sizeof(struct opalcore), GFP_KERNEL);
0085 }
0086 
0087 static inline int is_opalcore_usable(void)
0088 {
0089     return (oc_conf && oc_conf->opalcorebuf != NULL) ? 1 : 0;
0090 }
0091 
0092 static Elf64_Word *__init append_elf64_note(Elf64_Word *buf, char *name,
0093                      u32 type, void *data,
0094                      size_t data_len)
0095 {
0096     Elf64_Nhdr *note = (Elf64_Nhdr *)buf;
0097     Elf64_Word namesz = strlen(name) + 1;
0098 
0099     note->n_namesz = cpu_to_be32(namesz);
0100     note->n_descsz = cpu_to_be32(data_len);
0101     note->n_type   = cpu_to_be32(type);
0102     buf += DIV_ROUND_UP(sizeof(*note), sizeof(Elf64_Word));
0103     memcpy(buf, name, namesz);
0104     buf += DIV_ROUND_UP(namesz, sizeof(Elf64_Word));
0105     memcpy(buf, data, data_len);
0106     buf += DIV_ROUND_UP(data_len, sizeof(Elf64_Word));
0107 
0108     return buf;
0109 }
0110 
0111 static void __init fill_prstatus(struct elf_prstatus *prstatus, int pir,
0112               struct pt_regs *regs)
0113 {
0114     memset(prstatus, 0, sizeof(struct elf_prstatus));
0115     elf_core_copy_regs(&(prstatus->pr_reg), regs);
0116 
0117     /*
0118      * Overload PID with PIR value.
0119      * As a PIR value could also be '0', add an offset of '100'
0120      * to every PIR to avoid misinterpretations in GDB.
0121      */
0122     prstatus->common.pr_pid  = cpu_to_be32(100 + pir);
0123     prstatus->common.pr_ppid = cpu_to_be32(1);
0124 
0125     /*
0126      * Indicate SIGUSR1 for crash initiated from kernel.
0127      * SIGTERM otherwise.
0128      */
0129     if (pir == oc_conf->crashing_cpu) {
0130         short sig;
0131 
0132         sig = kernel_initiated ? SIGUSR1 : SIGTERM;
0133         prstatus->common.pr_cursig = cpu_to_be16(sig);
0134     }
0135 }
0136 
0137 static Elf64_Word *__init auxv_to_elf64_notes(Elf64_Word *buf,
0138                        u64 opal_boot_entry)
0139 {
0140     Elf64_Off *bufp = (Elf64_Off *)oc_conf->auxv_buf;
0141     int idx = 0;
0142 
0143     memset(bufp, 0, AUXV_DESC_SZ);
0144 
0145     /* Entry point of OPAL */
0146     bufp[idx++] = cpu_to_be64(AT_ENTRY);
0147     bufp[idx++] = cpu_to_be64(opal_boot_entry);
0148 
0149     /* end of vector */
0150     bufp[idx++] = cpu_to_be64(AT_NULL);
0151 
0152     buf = append_elf64_note(buf, CRASH_CORE_NOTE_NAME, NT_AUXV,
0153                 oc_conf->auxv_buf, AUXV_DESC_SZ);
0154     return buf;
0155 }
0156 
0157 /*
0158  * Read from the ELF header and then the crash dump.
0159  * Returns number of bytes read on success, -errno on failure.
0160  */
0161 static ssize_t read_opalcore(struct file *file, struct kobject *kobj,
0162                  struct bin_attribute *bin_attr, char *to,
0163                  loff_t pos, size_t count)
0164 {
0165     struct opalcore *m;
0166     ssize_t tsz, avail;
0167     loff_t tpos = pos;
0168 
0169     if (pos >= oc_conf->opalcore_size)
0170         return 0;
0171 
0172     /* Adjust count if it goes beyond opalcore size */
0173     avail = oc_conf->opalcore_size - pos;
0174     if (count > avail)
0175         count = avail;
0176 
0177     if (count == 0)
0178         return 0;
0179 
0180     /* Read ELF core header and/or PT_NOTE segment */
0181     if (tpos < oc_conf->opalcorebuf_sz) {
0182         tsz = min_t(size_t, oc_conf->opalcorebuf_sz - tpos, count);
0183         memcpy(to, oc_conf->opalcorebuf + tpos, tsz);
0184         to += tsz;
0185         tpos += tsz;
0186         count -= tsz;
0187     }
0188 
0189     list_for_each_entry(m, &opalcore_list, list) {
0190         /* nothing more to read here */
0191         if (count == 0)
0192             break;
0193 
0194         if (tpos < m->offset + m->size) {
0195             void *addr;
0196 
0197             tsz = min_t(size_t, m->offset + m->size - tpos, count);
0198             addr = (void *)(m->paddr + tpos - m->offset);
0199             memcpy(to, __va(addr), tsz);
0200             to += tsz;
0201             tpos += tsz;
0202             count -= tsz;
0203         }
0204     }
0205 
0206     return (tpos - pos);
0207 }
0208 
0209 static struct bin_attribute opal_core_attr = {
0210     .attr = {.name = "core", .mode = 0400},
0211     .read = read_opalcore
0212 };
0213 
0214 /*
0215  * Read CPU state dump data and convert it into ELF notes.
0216  *
0217  * Each register entry is of 16 bytes, A numerical identifier along with
0218  * a GPR/SPR flag in the first 8 bytes and the register value in the next
0219  * 8 bytes. For more details refer to F/W documentation.
0220  */
0221 static Elf64_Word * __init opalcore_append_cpu_notes(Elf64_Word *buf)
0222 {
0223     u32 thread_pir, size_per_thread, regs_offset, regs_cnt, reg_esize;
0224     struct hdat_fadump_thread_hdr *thdr;
0225     struct elf_prstatus prstatus;
0226     Elf64_Word *first_cpu_note;
0227     struct pt_regs regs;
0228     char *bufp;
0229     int i;
0230 
0231     size_per_thread = oc_conf->cpu_state_entry_size;
0232     bufp = __va(oc_conf->cpu_state_destination_vaddr);
0233 
0234     /*
0235      * Offset for register entries, entry size and registers count is
0236      * duplicated in every thread header in keeping with HDAT format.
0237      * Use these values from the first thread header.
0238      */
0239     thdr = (struct hdat_fadump_thread_hdr *)bufp;
0240     regs_offset = (offsetof(struct hdat_fadump_thread_hdr, offset) +
0241                be32_to_cpu(thdr->offset));
0242     reg_esize = be32_to_cpu(thdr->esize);
0243     regs_cnt  = be32_to_cpu(thdr->ecnt);
0244 
0245     pr_debug("--------CPU State Data------------\n");
0246     pr_debug("NumCpus     : %u\n", oc_conf->num_cpus);
0247     pr_debug("\tOffset: %u, Entry size: %u, Cnt: %u\n",
0248          regs_offset, reg_esize, regs_cnt);
0249 
0250     /*
0251      * Skip past the first CPU note. Fill this note with the
0252      * crashing CPU's prstatus.
0253      */
0254     first_cpu_note = buf;
0255     buf = append_elf64_note(buf, CRASH_CORE_NOTE_NAME, NT_PRSTATUS,
0256                 &prstatus, sizeof(prstatus));
0257 
0258     for (i = 0; i < oc_conf->num_cpus; i++, bufp += size_per_thread) {
0259         thdr = (struct hdat_fadump_thread_hdr *)bufp;
0260         thread_pir = be32_to_cpu(thdr->pir);
0261 
0262         pr_debug("[%04d] PIR: 0x%x, core state: 0x%02x\n",
0263              i, thread_pir, thdr->core_state);
0264 
0265         /*
0266          * Register state data of MAX cores is provided by firmware,
0267          * but some of this cores may not be active. So, while
0268          * processing register state data, check core state and
0269          * skip threads that belong to inactive cores.
0270          */
0271         if (thdr->core_state == HDAT_FADUMP_CORE_INACTIVE)
0272             continue;
0273 
0274         opal_fadump_read_regs((bufp + regs_offset), regs_cnt,
0275                       reg_esize, false, &regs);
0276 
0277         pr_debug("PIR 0x%x - R1 : 0x%llx, NIP : 0x%llx\n", thread_pir,
0278              be64_to_cpu(regs.gpr[1]), be64_to_cpu(regs.nip));
0279         fill_prstatus(&prstatus, thread_pir, &regs);
0280 
0281         if (thread_pir != oc_conf->crashing_cpu) {
0282             buf = append_elf64_note(buf, CRASH_CORE_NOTE_NAME,
0283                         NT_PRSTATUS, &prstatus,
0284                         sizeof(prstatus));
0285         } else {
0286             /*
0287              * Add crashing CPU as the first NT_PRSTATUS note for
0288              * GDB to process the core file appropriately.
0289              */
0290             append_elf64_note(first_cpu_note, CRASH_CORE_NOTE_NAME,
0291                       NT_PRSTATUS, &prstatus,
0292                       sizeof(prstatus));
0293         }
0294     }
0295 
0296     return buf;
0297 }
0298 
0299 static int __init create_opalcore(void)
0300 {
0301     u64 opal_boot_entry, opal_base_addr, paddr;
0302     u32 hdr_size, cpu_notes_size, count;
0303     struct device_node *dn;
0304     struct opalcore *new;
0305     loff_t opalcore_off;
0306     struct page *page;
0307     Elf64_Phdr *phdr;
0308     Elf64_Ehdr *elf;
0309     int i, ret;
0310     char *bufp;
0311 
0312     /* Get size of header & CPU notes for OPAL core */
0313     hdr_size = (sizeof(Elf64_Ehdr) +
0314             ((oc_conf->ptload_cnt + 1) * sizeof(Elf64_Phdr)));
0315     cpu_notes_size = ((oc_conf->num_cpus * (CRASH_CORE_NOTE_HEAD_BYTES +
0316               CRASH_CORE_NOTE_NAME_BYTES +
0317               CRASH_CORE_NOTE_DESC_BYTES)) +
0318               (CRASH_CORE_NOTE_HEAD_BYTES +
0319               CRASH_CORE_NOTE_NAME_BYTES + AUXV_DESC_SZ));
0320 
0321     /* Allocate buffer to setup OPAL core */
0322     oc_conf->opalcorebuf_sz = PAGE_ALIGN(hdr_size + cpu_notes_size);
0323     oc_conf->opalcorebuf = alloc_pages_exact(oc_conf->opalcorebuf_sz,
0324                          GFP_KERNEL | __GFP_ZERO);
0325     if (!oc_conf->opalcorebuf) {
0326         pr_err("Not enough memory to setup OPAL core (size: %lu)\n",
0327                oc_conf->opalcorebuf_sz);
0328         oc_conf->opalcorebuf_sz = 0;
0329         return -ENOMEM;
0330     }
0331     count = oc_conf->opalcorebuf_sz / PAGE_SIZE;
0332     page = virt_to_page(oc_conf->opalcorebuf);
0333     for (i = 0; i < count; i++)
0334         mark_page_reserved(page + i);
0335 
0336     pr_debug("opalcorebuf = 0x%llx\n", (u64)oc_conf->opalcorebuf);
0337 
0338     /* Read OPAL related device-tree entries */
0339     dn = of_find_node_by_name(NULL, "ibm,opal");
0340     if (dn) {
0341         ret = of_property_read_u64(dn, "opal-base-address",
0342                        &opal_base_addr);
0343         pr_debug("opal-base-address: %llx\n", opal_base_addr);
0344         ret |= of_property_read_u64(dn, "opal-boot-address",
0345                         &opal_boot_entry);
0346         pr_debug("opal-boot-address: %llx\n", opal_boot_entry);
0347     }
0348     if (!dn || ret)
0349         pr_warn("WARNING: Failed to read OPAL base & entry values\n");
0350 
0351     /* Use count to keep track of the program headers */
0352     count = 0;
0353 
0354     bufp = oc_conf->opalcorebuf;
0355     elf = (Elf64_Ehdr *)bufp;
0356     bufp += sizeof(Elf64_Ehdr);
0357     memcpy(elf->e_ident, ELFMAG, SELFMAG);
0358     elf->e_ident[EI_CLASS] = ELF_CLASS;
0359     elf->e_ident[EI_DATA] = ELFDATA2MSB;
0360     elf->e_ident[EI_VERSION] = EV_CURRENT;
0361     elf->e_ident[EI_OSABI] = ELF_OSABI;
0362     memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
0363     elf->e_type = cpu_to_be16(ET_CORE);
0364     elf->e_machine = cpu_to_be16(ELF_ARCH);
0365     elf->e_version = cpu_to_be32(EV_CURRENT);
0366     elf->e_entry = 0;
0367     elf->e_phoff = cpu_to_be64(sizeof(Elf64_Ehdr));
0368     elf->e_shoff = 0;
0369     elf->e_flags = 0;
0370 
0371     elf->e_ehsize = cpu_to_be16(sizeof(Elf64_Ehdr));
0372     elf->e_phentsize = cpu_to_be16(sizeof(Elf64_Phdr));
0373     elf->e_phnum = 0;
0374     elf->e_shentsize = 0;
0375     elf->e_shnum = 0;
0376     elf->e_shstrndx = 0;
0377 
0378     phdr = (Elf64_Phdr *)bufp;
0379     bufp += sizeof(Elf64_Phdr);
0380     phdr->p_type    = cpu_to_be32(PT_NOTE);
0381     phdr->p_flags   = 0;
0382     phdr->p_align   = 0;
0383     phdr->p_paddr   = phdr->p_vaddr = 0;
0384     phdr->p_offset  = cpu_to_be64(hdr_size);
0385     phdr->p_filesz  = phdr->p_memsz = cpu_to_be64(cpu_notes_size);
0386     count++;
0387 
0388     opalcore_off = oc_conf->opalcorebuf_sz;
0389     oc_conf->ptload_phdr  = (Elf64_Phdr *)bufp;
0390     paddr = 0;
0391     for (i = 0; i < oc_conf->ptload_cnt; i++) {
0392         phdr = (Elf64_Phdr *)bufp;
0393         bufp += sizeof(Elf64_Phdr);
0394         phdr->p_type    = cpu_to_be32(PT_LOAD);
0395         phdr->p_flags   = cpu_to_be32(PF_R|PF_W|PF_X);
0396         phdr->p_align   = 0;
0397 
0398         new = get_new_element();
0399         if (!new)
0400             return -ENOMEM;
0401         new->paddr  = oc_conf->ptload_addr[i];
0402         new->size   = oc_conf->ptload_size[i];
0403         new->offset = opalcore_off;
0404         list_add_tail(&new->list, &opalcore_list);
0405 
0406         phdr->p_paddr   = cpu_to_be64(paddr);
0407         phdr->p_vaddr   = cpu_to_be64(opal_base_addr + paddr);
0408         phdr->p_filesz  = phdr->p_memsz  =
0409             cpu_to_be64(oc_conf->ptload_size[i]);
0410         phdr->p_offset  = cpu_to_be64(opalcore_off);
0411 
0412         count++;
0413         opalcore_off += oc_conf->ptload_size[i];
0414         paddr += oc_conf->ptload_size[i];
0415     }
0416 
0417     elf->e_phnum = cpu_to_be16(count);
0418 
0419     bufp = (char *)opalcore_append_cpu_notes((Elf64_Word *)bufp);
0420     bufp = (char *)auxv_to_elf64_notes((Elf64_Word *)bufp, opal_boot_entry);
0421 
0422     oc_conf->opalcore_size = opalcore_off;
0423     return 0;
0424 }
0425 
0426 static void opalcore_cleanup(void)
0427 {
0428     if (oc_conf == NULL)
0429         return;
0430 
0431     /* Remove OPAL core sysfs file */
0432     sysfs_remove_bin_file(mpipl_kobj, &opal_core_attr);
0433     oc_conf->ptload_phdr = NULL;
0434     oc_conf->ptload_cnt = 0;
0435 
0436     /* free the buffer used for setting up OPAL core */
0437     if (oc_conf->opalcorebuf) {
0438         void *end = (void *)((u64)oc_conf->opalcorebuf +
0439                      oc_conf->opalcorebuf_sz);
0440 
0441         free_reserved_area(oc_conf->opalcorebuf, end, -1, NULL);
0442         oc_conf->opalcorebuf = NULL;
0443         oc_conf->opalcorebuf_sz = 0;
0444     }
0445 
0446     kfree(oc_conf);
0447     oc_conf = NULL;
0448 }
0449 __exitcall(opalcore_cleanup);
0450 
0451 static void __init opalcore_config_init(void)
0452 {
0453     u32 idx, cpu_data_version;
0454     struct device_node *np;
0455     const __be32 *prop;
0456     u64 addr = 0;
0457     int i, ret;
0458 
0459     np = of_find_node_by_path("/ibm,opal/dump");
0460     if (np == NULL)
0461         return;
0462 
0463     if (!of_device_is_compatible(np, "ibm,opal-dump")) {
0464         pr_warn("Support missing for this f/w version!\n");
0465         return;
0466     }
0467 
0468     /* Check if dump has been initiated on last reboot */
0469     prop = of_get_property(np, "mpipl-boot", NULL);
0470     if (!prop) {
0471         of_node_put(np);
0472         return;
0473     }
0474 
0475     /* Get OPAL metadata */
0476     ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_OPAL, &addr);
0477     if ((ret != OPAL_SUCCESS) || !addr) {
0478         pr_err("Failed to get OPAL metadata (%d)\n", ret);
0479         goto error_out;
0480     }
0481 
0482     addr = be64_to_cpu(addr);
0483     pr_debug("OPAL metadata addr: %llx\n", addr);
0484     opalc_metadata = __va(addr);
0485 
0486     /* Get OPAL CPU metadata */
0487     ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_CPU, &addr);
0488     if ((ret != OPAL_SUCCESS) || !addr) {
0489         pr_err("Failed to get OPAL CPU metadata (%d)\n", ret);
0490         goto error_out;
0491     }
0492 
0493     addr = be64_to_cpu(addr);
0494     pr_debug("CPU metadata addr: %llx\n", addr);
0495     opalc_cpu_metadata = __va(addr);
0496 
0497     /* Allocate memory for config buffer */
0498     oc_conf = kzalloc(sizeof(struct opalcore_config), GFP_KERNEL);
0499     if (oc_conf == NULL)
0500         goto error_out;
0501 
0502     /* Parse OPAL metadata */
0503     if (opalc_metadata->version != OPAL_MPIPL_VERSION) {
0504         pr_warn("Supported OPAL metadata version: %u, found: %u!\n",
0505             OPAL_MPIPL_VERSION, opalc_metadata->version);
0506         pr_warn("WARNING: F/W using newer OPAL metadata format!!\n");
0507     }
0508 
0509     oc_conf->ptload_cnt = 0;
0510     idx = be32_to_cpu(opalc_metadata->region_cnt);
0511     if (idx > MAX_PT_LOAD_CNT) {
0512         pr_warn("WARNING: OPAL regions count (%d) adjusted to limit (%d)",
0513             idx, MAX_PT_LOAD_CNT);
0514         idx = MAX_PT_LOAD_CNT;
0515     }
0516     for (i = 0; i < idx; i++) {
0517         oc_conf->ptload_addr[oc_conf->ptload_cnt] =
0518                 be64_to_cpu(opalc_metadata->region[i].dest);
0519         oc_conf->ptload_size[oc_conf->ptload_cnt++] =
0520                 be64_to_cpu(opalc_metadata->region[i].size);
0521     }
0522     oc_conf->ptload_cnt = i;
0523     oc_conf->crashing_cpu = be32_to_cpu(opalc_metadata->crashing_pir);
0524 
0525     if (!oc_conf->ptload_cnt) {
0526         pr_err("OPAL memory regions not found\n");
0527         goto error_out;
0528     }
0529 
0530     /* Parse OPAL CPU metadata */
0531     cpu_data_version = be32_to_cpu(opalc_cpu_metadata->cpu_data_version);
0532     if (cpu_data_version != HDAT_FADUMP_CPU_DATA_VER) {
0533         pr_warn("Supported CPU data version: %u, found: %u!\n",
0534             HDAT_FADUMP_CPU_DATA_VER, cpu_data_version);
0535         pr_warn("WARNING: F/W using newer CPU state data format!!\n");
0536     }
0537 
0538     addr = be64_to_cpu(opalc_cpu_metadata->region[0].dest);
0539     if (!addr) {
0540         pr_err("CPU state data not found!\n");
0541         goto error_out;
0542     }
0543     oc_conf->cpu_state_destination_vaddr = (u64)__va(addr);
0544 
0545     oc_conf->cpu_state_data_size =
0546             be64_to_cpu(opalc_cpu_metadata->region[0].size);
0547     oc_conf->cpu_state_entry_size =
0548             be32_to_cpu(opalc_cpu_metadata->cpu_data_size);
0549 
0550     if ((oc_conf->cpu_state_entry_size == 0) ||
0551         (oc_conf->cpu_state_entry_size > oc_conf->cpu_state_data_size)) {
0552         pr_err("CPU state data is invalid.\n");
0553         goto error_out;
0554     }
0555     oc_conf->num_cpus = (oc_conf->cpu_state_data_size /
0556                  oc_conf->cpu_state_entry_size);
0557 
0558     of_node_put(np);
0559     return;
0560 
0561 error_out:
0562     pr_err("Could not export /sys/firmware/opal/core\n");
0563     opalcore_cleanup();
0564     of_node_put(np);
0565 }
0566 
0567 static ssize_t release_core_store(struct kobject *kobj,
0568                   struct kobj_attribute *attr,
0569                   const char *buf, size_t count)
0570 {
0571     int input = -1;
0572 
0573     if (kstrtoint(buf, 0, &input))
0574         return -EINVAL;
0575 
0576     if (input == 1) {
0577         if (oc_conf == NULL) {
0578             pr_err("'/sys/firmware/opal/core' file not accessible!\n");
0579             return -EPERM;
0580         }
0581 
0582         /*
0583          * Take away '/sys/firmware/opal/core' and release all memory
0584          * used for exporting this file.
0585          */
0586         opalcore_cleanup();
0587     } else
0588         return -EINVAL;
0589 
0590     return count;
0591 }
0592 
0593 static struct kobj_attribute opalcore_rel_attr = __ATTR_WO(release_core);
0594 
0595 static struct attribute *mpipl_attr[] = {
0596     &opalcore_rel_attr.attr,
0597     NULL,
0598 };
0599 
0600 static struct bin_attribute *mpipl_bin_attr[] = {
0601     &opal_core_attr,
0602     NULL,
0603 
0604 };
0605 
0606 static const struct attribute_group mpipl_group = {
0607     .attrs = mpipl_attr,
0608     .bin_attrs =  mpipl_bin_attr,
0609 };
0610 
0611 static int __init opalcore_init(void)
0612 {
0613     int rc = -1;
0614 
0615     opalcore_config_init();
0616 
0617     if (oc_conf == NULL)
0618         return rc;
0619 
0620     create_opalcore();
0621 
0622     /*
0623      * If oc_conf->opalcorebuf= is set in the 2nd kernel,
0624      * then capture the dump.
0625      */
0626     if (!(is_opalcore_usable())) {
0627         pr_err("Failed to export /sys/firmware/opal/mpipl/core\n");
0628         opalcore_cleanup();
0629         return rc;
0630     }
0631 
0632     /* Set OPAL core file size */
0633     opal_core_attr.size = oc_conf->opalcore_size;
0634 
0635     mpipl_kobj = kobject_create_and_add("mpipl", opal_kobj);
0636     if (!mpipl_kobj) {
0637         pr_err("unable to create mpipl kobject\n");
0638         return -ENOMEM;
0639     }
0640 
0641     /* Export OPAL core sysfs file */
0642     rc = sysfs_create_group(mpipl_kobj, &mpipl_group);
0643     if (rc) {
0644         pr_err("mpipl sysfs group creation failed (%d)", rc);
0645         opalcore_cleanup();
0646         return rc;
0647     }
0648     /* The /sys/firmware/opal/core is moved to /sys/firmware/opal/mpipl/
0649      * directory, need to create symlink at old location to maintain
0650      * backward compatibility.
0651      */
0652     rc = compat_only_sysfs_link_entry_to_kobj(opal_kobj, mpipl_kobj,
0653                           "core", NULL);
0654     if (rc) {
0655         pr_err("unable to create core symlink (%d)\n", rc);
0656         return rc;
0657     }
0658 
0659     return 0;
0660 }
0661 fs_initcall(opalcore_init);