static ssize_t tpm_store_ppi_request(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { u32 req; u64 ret; int func = TPM_PPI_FN_SUBREQ; union acpi_object *obj, tmp; union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp); struct tpm_chip *chip = to_tpm_chip(dev); /* * the function to submit TPM operation request to pre-os environment * is updated with function index from SUBREQ to SUBREQ2 since PPI * version 1.1 */ if (acpi_check_dsm(chip->acpi_dev_handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_SUBREQ2)) func = TPM_PPI_FN_SUBREQ2; /* * PPI spec defines params[3].type as ACPI_TYPE_PACKAGE. Some BIOS * accept buffer/string/integer type, but some BIOS accept buffer/ * string/package type. For PPI version 1.0 and 1.1, use buffer type * for compatibility, and use package type since 1.2 according to spec. */ if (strcmp(chip->ppi_version, "1.2") < 0) { if (sscanf(buf, "%d", &req) != 1) return -EINVAL; argv4.type = ACPI_TYPE_BUFFER; argv4.buffer.length = sizeof(req); argv4.buffer.pointer = (u8 *)&req; } else { tmp.type = ACPI_TYPE_INTEGER; if (sscanf(buf, "%llu", &tmp.integer.value) != 1) return -EINVAL; } obj = tpm_eval_dsm(chip->acpi_dev_handle, func, ACPI_TYPE_INTEGER, &argv4); if (!obj) { return -ENXIO; } else { ret = obj->integer.value; ACPI_FREE(obj); } if (ret == 0) return (acpi_status)count; return (ret == 1) ? -EPERM : -EFAULT; }
static ssize_t show_ppi_operations(acpi_handle dev_handle, char *buf, u32 start, u32 end) { int i; u32 ret; char *str = buf; union acpi_object *obj, tmp; union acpi_object argv = ACPI_INIT_DSM_ARGV4(1, &tmp); static char *info[] = { "Not implemented", "BIOS only", "Blocked for OS by BIOS", "User required", "User not required", }; if (!acpi_check_dsm(dev_handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_GETOPR)) return -EPERM; tmp.integer.type = ACPI_TYPE_INTEGER; for (i = start; i <= end; i++) { tmp.integer.value = i; obj = tpm_eval_dsm(dev_handle, TPM_PPI_FN_GETOPR, ACPI_TYPE_INTEGER, &argv); if (!obj) { return -ENOMEM; } else { ret = obj->integer.value; ACPI_FREE(obj); } if (ret > 0 && ret < ARRAY_SIZE(info)) str += scnprintf(str, PAGE_SIZE, "%d %d: %s\n", i, ret, info[ret]); } return str - buf; }
static int dwc3_pci_dsm(struct dwc3_pci *dwc, int param) { union acpi_object *obj; union acpi_object tmp; union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp); if (!dwc->has_dsm_for_pm) return 0; tmp.type = ACPI_TYPE_INTEGER; tmp.integer.value = param; obj = acpi_evaluate_dsm(ACPI_HANDLE(&dwc->pci->dev), &dwc->guid, 1, PCI_INTEL_BXT_FUNC_PMU_PWR, &argv4); if (!obj) { dev_err(&dwc->pci->dev, "failed to evaluate _DSM\n"); return -EIO; } ACPI_FREE(obj); return 0; }