Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

sed-opal: add IOC_OPAL_GET_SUM_STATUS ioctl.

This adds a function for retrieving the set of Locking objects enabled
for Single User Mode (SUM) and the value of the
RangeStartRangeLengthPolicy parameter.

It retrieves data from the LockingInfo table, specifically the
columns SingleUserModeRanges and RangeStartLengthPolicy, which
were added according to the TCG Opal Feature Set: Single User Mode,
as described in chapters 4.4.3.1 and 4.4.3.2.

Signed-off-by: Ondrej Kozina <okozina@redhat.com>
Reviewed-and-tested-by: Milan Broz <gmazyland@gmail.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Ondrej Kozina and committed by
Jens Axboe
0cc9293b 661025cd

+173
+159
block/sed-opal.c
··· 1757 1757 OPAL_ADMINSP_UID, NULL, 0); 1758 1758 } 1759 1759 1760 + static int start_anybodyLSP_opal_session(struct opal_dev *dev, void *data) 1761 + { 1762 + return start_generic_opal_session(dev, OPAL_ANYBODY_UID, 1763 + OPAL_LOCKINGSP_UID, NULL, 0); 1764 + } 1765 + 1760 1766 static int start_SIDASP_opal_session(struct opal_dev *dev, void *data) 1761 1767 { 1762 1768 int ret; ··· 3395 3389 return 0; 3396 3390 } 3397 3391 3392 + static int get_sum_ranges(struct opal_dev *dev, void *data) 3393 + { 3394 + const char *lr_uid; 3395 + size_t lr_uid_len; 3396 + u64 val; 3397 + const struct opal_resp_tok *tok; 3398 + int err, tok_n = 2; 3399 + struct opal_sum_ranges *sranges = data; 3400 + const __u8 lr_all[OPAL_MAX_LRS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; 3401 + 3402 + err = generic_get_columns(dev, opaluid[OPAL_LOCKING_INFO_TABLE], OPAL_SUM_SET_LIST, 3403 + OPAL_SUM_RANGE_POLICY); 3404 + if (err) { 3405 + pr_debug("Couldn't get locking info table columns %d to %d.\n", 3406 + OPAL_SUM_SET_LIST, OPAL_SUM_RANGE_POLICY); 3407 + return err; 3408 + } 3409 + 3410 + tok = response_get_token(&dev->parsed, tok_n); 3411 + if (IS_ERR(tok)) 3412 + return PTR_ERR(tok); 3413 + 3414 + if (!response_token_matches(tok, OPAL_STARTNAME)) { 3415 + pr_debug("Unexpected response token type %d.\n", tok_n); 3416 + return OPAL_INVAL_PARAM; 3417 + } 3418 + tok_n++; 3419 + 3420 + if (response_get_u64(&dev->parsed, tok_n) != OPAL_SUM_SET_LIST) { 3421 + pr_debug("Token %d does not match expected column %u.\n", 3422 + tok_n, OPAL_SUM_SET_LIST); 3423 + return OPAL_INVAL_PARAM; 3424 + } 3425 + tok_n++; 3426 + 3427 + tok = response_get_token(&dev->parsed, tok_n); 3428 + if (IS_ERR(tok)) 3429 + return PTR_ERR(tok); 3430 + 3431 + /* 3432 + * The OPAL_SUM_SET_LIST response contains two distinct values: 3433 + * 3434 + * - the list of individual locking ranges (UIDs) put in SUM. The list 3435 + * may also be empty signaling the SUM is disabled. 3436 + * 3437 + * - the Locking table UID if the entire Locking table is put in SUM. 3438 + */ 3439 + if (response_token_matches(tok, OPAL_STARTLIST)) { 3440 + sranges->num_lrs = 0; 3441 + 3442 + tok_n++; 3443 + tok = response_get_token(&dev->parsed, tok_n); 3444 + if (IS_ERR(tok)) 3445 + return PTR_ERR(tok); 3446 + 3447 + while (!response_token_matches(tok, OPAL_ENDLIST)) { 3448 + lr_uid_len = response_get_string(&dev->parsed, tok_n, &lr_uid); 3449 + if (lr_uid_len != OPAL_UID_LENGTH) { 3450 + pr_debug("Unexpected response token type %d.\n", tok_n); 3451 + return OPAL_INVAL_PARAM; 3452 + } 3453 + 3454 + if (memcmp(lr_uid, opaluid[OPAL_LOCKINGRANGE_GLOBAL], OPAL_UID_LENGTH)) { 3455 + if (lr_uid[5] != LOCKING_RANGE_NON_GLOBAL) { 3456 + pr_debug("Unexpected byte %d at LR UUID position 5.\n", 3457 + lr_uid[5]); 3458 + return OPAL_INVAL_PARAM; 3459 + } 3460 + sranges->lr[sranges->num_lrs++] = lr_uid[7]; 3461 + } else 3462 + sranges->lr[sranges->num_lrs++] = 0; 3463 + 3464 + tok_n++; 3465 + tok = response_get_token(&dev->parsed, tok_n); 3466 + if (IS_ERR(tok)) 3467 + return PTR_ERR(tok); 3468 + } 3469 + } else { 3470 + /* Only OPAL_LOCKING_TABLE UID is an alternative to OPAL_STARTLIST here. */ 3471 + lr_uid_len = response_get_string(&dev->parsed, tok_n, &lr_uid); 3472 + if (lr_uid_len != OPAL_UID_LENGTH) { 3473 + pr_debug("Unexpected response token type %d.\n", tok_n); 3474 + return OPAL_INVAL_PARAM; 3475 + } 3476 + 3477 + if (memcmp(lr_uid, opaluid[OPAL_LOCKING_TABLE], OPAL_UID_LENGTH)) { 3478 + pr_debug("Unexpected response UID.\n"); 3479 + return OPAL_INVAL_PARAM; 3480 + } 3481 + 3482 + /* sed-opal kernel API already provides following limit in Activate command */ 3483 + sranges->num_lrs = OPAL_MAX_LRS; 3484 + memcpy(sranges->lr, lr_all, OPAL_MAX_LRS); 3485 + } 3486 + tok_n++; 3487 + 3488 + tok = response_get_token(&dev->parsed, tok_n); 3489 + if (IS_ERR(tok)) 3490 + return PTR_ERR(tok); 3491 + 3492 + if (!response_token_matches(tok, OPAL_ENDNAME)) { 3493 + pr_debug("Unexpected response token type %d.\n", tok_n); 3494 + return OPAL_INVAL_PARAM; 3495 + } 3496 + tok_n++; 3497 + 3498 + err = response_get_column(&dev->parsed, &tok_n, OPAL_SUM_RANGE_POLICY, &val); 3499 + if (err) 3500 + return err; 3501 + 3502 + sranges->range_policy = val ? 1 : 0; 3503 + 3504 + return 0; 3505 + } 3506 + 3507 + static int opal_get_sum_ranges(struct opal_dev *dev, struct opal_sum_ranges *opal_sum_rngs, 3508 + void __user *data) 3509 + { 3510 + const struct opal_step admin_steps[] = { 3511 + { start_admin1LSP_opal_session, &opal_sum_rngs->key }, 3512 + { get_sum_ranges, opal_sum_rngs }, 3513 + { end_opal_session, } 3514 + }, anybody_steps[] = { 3515 + { start_anybodyLSP_opal_session, NULL }, 3516 + { get_sum_ranges, opal_sum_rngs }, 3517 + { end_opal_session, } 3518 + }; 3519 + int ret; 3520 + 3521 + mutex_lock(&dev->dev_lock); 3522 + setup_opal_dev(dev); 3523 + if (opal_sum_rngs->key.key_len) 3524 + /* Use Admin1 session (authenticated by PIN) to retrieve LockingInfo columns */ 3525 + ret = execute_steps(dev, admin_steps, ARRAY_SIZE(admin_steps)); 3526 + else 3527 + /* Use Anybody session (no key) to retrieve LockingInfo columns */ 3528 + ret = execute_steps(dev, anybody_steps, ARRAY_SIZE(anybody_steps)); 3529 + mutex_unlock(&dev->dev_lock); 3530 + 3531 + /* skip session info when copying back to uspace */ 3532 + if (!ret && copy_to_user(data + offsetof(struct opal_sum_ranges, num_lrs), 3533 + (void *)opal_sum_rngs + offsetof(struct opal_sum_ranges, num_lrs), 3534 + sizeof(*opal_sum_rngs) - offsetof(struct opal_sum_ranges, num_lrs))) { 3535 + pr_debug("Error copying SUM ranges info to userspace\n"); 3536 + return -EFAULT; 3537 + } 3538 + 3539 + return ret; 3540 + } 3541 + 3398 3542 int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg) 3399 3543 { 3400 3544 void *p; ··· 3638 3482 break; 3639 3483 case IOC_OPAL_ENABLE_DISABLE_LR: 3640 3484 ret = opal_enable_disable_range(dev, p); 3485 + break; 3486 + case IOC_OPAL_GET_SUM_STATUS: 3487 + ret = opal_get_sum_ranges(dev, p, arg); 3641 3488 break; 3642 3489 3643 3490 default:
+1
include/linux/sed-opal.h
··· 56 56 case IOC_OPAL_REACTIVATE_LSP: 57 57 case IOC_OPAL_LR_SET_START_LEN: 58 58 case IOC_OPAL_ENABLE_DISABLE_LR: 59 + case IOC_OPAL_GET_SUM_STATUS: 59 60 return true; 60 61 } 61 62 return false;
+13
include/uapi/linux/sed-opal.h
··· 111 111 __u8 align[4]; 112 112 }; 113 113 114 + struct opal_sum_ranges { 115 + /* 116 + * Initiate Admin1 session if key_len > 0, 117 + * use Anybody session otherwise. 118 + */ 119 + struct opal_key key; 120 + __u8 num_lrs; 121 + __u8 lr[OPAL_MAX_LRS]; 122 + __u8 range_policy; 123 + __u8 align[5]; /* Align to 8 byte boundary */ 124 + }; 125 + 114 126 struct opal_lock_unlock { 115 127 struct opal_session_info session; 116 128 __u32 l_state; ··· 244 232 #define IOC_OPAL_REACTIVATE_LSP _IOW('p', 242, struct opal_lr_react) 245 233 #define IOC_OPAL_LR_SET_START_LEN _IOW('p', 243, struct opal_user_lr_setup) 246 234 #define IOC_OPAL_ENABLE_DISABLE_LR _IOW('p', 244, struct opal_user_lr_setup) 235 + #define IOC_OPAL_GET_SUM_STATUS _IOW('p', 245, struct opal_sum_ranges) 247 236 248 237 #endif /* _UAPI_SED_OPAL_H */