staticint pseries_status_to_err(int rc)
{ int err;
switch (rc) { case H_SUCCESS:
err = 0; break; case H_FUNCTION:
err = -ENXIO; break; case H_PARAMETER: case H_P2: case H_P3: case H_P4: case H_P5: case H_P6:
err = -EINVAL; break; case H_NOT_FOUND:
err = -ENOENT; break; case H_BUSY: case H_LONG_BUSY_ORDER_1_MSEC: case H_LONG_BUSY_ORDER_10_MSEC: case H_LONG_BUSY_ORDER_100_MSEC: case H_LONG_BUSY_ORDER_1_SEC: case H_LONG_BUSY_ORDER_10_SEC: case H_LONG_BUSY_ORDER_100_SEC:
err = -EBUSY; break; case H_AUTHORITY:
err = -EPERM; break; case H_NO_MEM:
err = -ENOMEM; break; case H_RESOURCE:
err = -EEXIST; break; case H_TOO_BIG:
err = -EFBIG; break; case H_STATE:
err = -EIO; break; case H_R_STATE:
err = -EIO; break; case H_IN_USE:
err = -EEXIST; break; case H_ABORTED:
err = -EIO; break; default:
err = -EINVAL;
}
pr_debug("Converted hypervisor code %d to Linux %d\n", rc, err);
// If we booted from kexec, we could be reusing an existing password already if (ospassword) {
pr_debug("Password of length %u already in use\n", ospasswordlength); return 0;
}
// The password must not cross a page boundary, so we align to the next power of 2
password = kzalloc(roundup_pow_of_two(maxpwsize), GFP_KERNEL); if (!password) return -ENOMEM;
if (consumer > PLPKS_OS_OWNER) return ERR_PTR(-EINVAL);
// The auth structure must not cross a page boundary and must be // 16 byte aligned. We align to the next largest power of 2
auth = kzalloc(roundup_pow_of_two(struct_size(auth, password, maxpwsize)), GFP_KERNEL); if (!auth) return ERR_PTR(-ENOMEM);
auth->version = 1;
auth->consumer = consumer;
if (consumer == PLPKS_FW_OWNER || consumer == PLPKS_BOOTLOADER_OWNER) return auth;
/* * Label is combination of label attributes + name. * Label attributes are used internally by kernel and not exposed to the user.
*/ staticstruct label *construct_label(char *component, u8 varos, u8 *name,
u16 namelen)
{ struct label *label;
size_t slen = 0;
if (!name || namelen > PLPKS_MAX_NAME_SIZE) return ERR_PTR(-EINVAL);
// Support NULL component for signed updates if (component) {
slen = strlen(component); if (slen > sizeof(label->attr.prefix)) return ERR_PTR(-EINVAL);
}
// The label structure must not cross a page boundary, so we align to the next power of 2
label = kzalloc(roundup_pow_of_two(sizeof(*label)), GFP_KERNEL); if (!label) return ERR_PTR(-ENOMEM);
if (component)
memcpy(&label->attr.prefix, component, slen);
// Config struct must not cross a page boundary. So long as the struct // size is a power of 2, this should be fine as alignment is guaranteed
config = kzalloc(size, GFP_KERNEL); if (!config) {
rc = -ENOMEM; goto err;
}
// Validate that the numbers we get back match the requirements of the spec if (maxpwsize < 32) {
pr_err("Invalid Max Password Size received from hypervisor (%d < 32)\n", maxpwsize);
rc = -EIO; goto err;
}
if (maxobjlabelsize < 255) {
pr_err("Invalid Max Object Label Size received from hypervisor (%d < 255)\n",
maxobjlabelsize);
rc = -EIO; goto err;
}
if (totalsize < 4096) {
pr_err("Invalid Total Size received from hypervisor (%d < 4096)\n", totalsize);
rc = -EIO; goto err;
}
u32 plpks_get_usedspace(void)
{ // Unlike other config values, usedspace regularly changes as objects // are updated, so we need to refresh. int rc = _plpks_get_config(); if (rc) {
pr_err("Couldn't get config, rc: %d\n", rc); return 0;
} return usedspace;
}
// Once a password is registered with the hypervisor it cannot be cleared without // rebooting the LPAR, so to keep using the PLPKS across kexec boots we need to // recover the previous password from the FDT. // // There are a few challenges here. We don't want the password to be visible to // users, so we need to clear it from the FDT. This has to be done in early boot. // Clearing it from the FDT would make the FDT's checksum invalid, so we have to // manually cause the checksum to be recalculated. void __init plpks_early_init_devtree(void)
{ void *fdt = initial_boot_params; int chosen_node = fdt_path_offset(fdt, "/chosen"); const u8 *password; int len;
out:
fdt_nop_property(fdt, chosen_node, "ibm,plpks-pw"); // Since we've cleared the password, we must update the FDT checksum
early_init_dt_verify(fdt, __pa(fdt));
}
static __init int pseries_plpks_init(void)
{ int rc;
if (!firmware_has_feature(FW_FEATURE_PLPKS)) return -ENODEV;
rc = _plpks_get_config();
if (rc) {
pr_err("POWER LPAR Platform KeyStore is not supported or enabled\n"); return rc;
}
rc = plpks_gen_password(); if (rc)
pr_err("Failed setting POWER LPAR Platform KeyStore Password\n"); else
pr_info("POWER LPAR Platform KeyStore initialized successfully\n");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.