summaryrefslogtreecommitdiffstats
path: root/block/sed-opal.c
diff options
context:
space:
mode:
authorJonas Rabenstein <jonas.rabenstein@studium.uni-erlangen.de>2019-05-21 16:46:45 -0400
committerJens Axboe <axboe@kernel.dk>2019-06-29 12:33:57 -0400
commita9b25b4cf2b76d320afc999f881ccb805fecdd84 (patch)
tree2137106246ef1e5ae9afdc4677a93c1df4ca22fa /block/sed-opal.c
parentc9888443413e4e06013e482fc484dbb9c559c145 (diff)
block: sed-opal: ioctl for writing to shadow mbr
Allow modification of the shadow mbr. If the shadow mbr is not marked as done, this data will be presented read only as the device content. Only after marking the shadow mbr as done and unlocking a locking range the actual content is accessible. Co-authored-by: David Kozub <zub@linux.fjfi.cvut.cz> Signed-off-by: Jonas Rabenstein <jonas.rabenstein@studium.uni-erlangen.de> Signed-off-by: David Kozub <zub@linux.fjfi.cvut.cz> Reviewed-by: Scott Bauer <sbauer@plzdonthack.me> Reviewed-by: Jon Derrick <jonathan.derrick@intel.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/sed-opal.c')
-rw-r--r--block/sed-opal.c91
1 files changed, 89 insertions, 2 deletions
diff --git a/block/sed-opal.c b/block/sed-opal.c
index f94f359dd688..b02ef2ff0d75 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -26,6 +26,9 @@
26#define IO_BUFFER_LENGTH 2048 26#define IO_BUFFER_LENGTH 2048
27#define MAX_TOKS 64 27#define MAX_TOKS 64
28 28
29/* Number of bytes needed by cmd_finalize. */
30#define CMD_FINALIZE_BYTES_NEEDED 7
31
29struct opal_step { 32struct opal_step {
30 int (*fn)(struct opal_dev *dev, void *data); 33 int (*fn)(struct opal_dev *dev, void *data);
31 void *data; 34 void *data;
@@ -523,12 +526,17 @@ static int opal_discovery0_step(struct opal_dev *dev)
523 return execute_step(dev, &discovery0_step, 0); 526 return execute_step(dev, &discovery0_step, 0);
524} 527}
525 528
529static size_t remaining_size(struct opal_dev *cmd)
530{
531 return IO_BUFFER_LENGTH - cmd->pos;
532}
533
526static bool can_add(int *err, struct opal_dev *cmd, size_t len) 534static bool can_add(int *err, struct opal_dev *cmd, size_t len)
527{ 535{
528 if (*err) 536 if (*err)
529 return false; 537 return false;
530 538
531 if (len > IO_BUFFER_LENGTH || cmd->pos > IO_BUFFER_LENGTH - len) { 539 if (remaining_size(cmd) < len) {
532 pr_debug("Error adding %zu bytes: end of buffer.\n", len); 540 pr_debug("Error adding %zu bytes: end of buffer.\n", len);
533 *err = -ERANGE; 541 *err = -ERANGE;
534 return false; 542 return false;
@@ -674,7 +682,11 @@ static int cmd_finalize(struct opal_dev *cmd, u32 hsn, u32 tsn)
674 struct opal_header *hdr; 682 struct opal_header *hdr;
675 int err = 0; 683 int err = 0;
676 684
677 /* close the parameter list opened from cmd_start */ 685 /*
686 * Close the parameter list opened from cmd_start.
687 * The number of bytes added must be equal to
688 * CMD_FINALIZE_BYTES_NEEDED.
689 */
678 add_token_u8(&err, cmd, OPAL_ENDLIST); 690 add_token_u8(&err, cmd, OPAL_ENDLIST);
679 691
680 add_token_u8(&err, cmd, OPAL_ENDOFDATA); 692 add_token_u8(&err, cmd, OPAL_ENDOFDATA);
@@ -1536,6 +1548,58 @@ static int set_mbr_enable_disable(struct opal_dev *dev, void *data)
1536 return finalize_and_send(dev, parse_and_check_status); 1548 return finalize_and_send(dev, parse_and_check_status);
1537} 1549}
1538 1550
1551static int write_shadow_mbr(struct opal_dev *dev, void *data)
1552{
1553 struct opal_shadow_mbr *shadow = data;
1554 const u8 __user *src;
1555 u8 *dst;
1556 size_t off = 0;
1557 u64 len;
1558 int err = 0;
1559
1560 /* do the actual transmission(s) */
1561 src = (u8 __user *)(uintptr_t)shadow->data;
1562 while (off < shadow->size) {
1563 err = cmd_start(dev, opaluid[OPAL_MBR], opalmethod[OPAL_SET]);
1564 add_token_u8(&err, dev, OPAL_STARTNAME);
1565 add_token_u8(&err, dev, OPAL_WHERE);
1566 add_token_u64(&err, dev, shadow->offset + off);
1567 add_token_u8(&err, dev, OPAL_ENDNAME);
1568
1569 add_token_u8(&err, dev, OPAL_STARTNAME);
1570 add_token_u8(&err, dev, OPAL_VALUES);
1571
1572 /*
1573 * The bytestring header is either 1 or 2 bytes, so assume 2.
1574 * There also needs to be enough space to accommodate the
1575 * trailing OPAL_ENDNAME (1 byte) and tokens added by
1576 * cmd_finalize.
1577 */
1578 len = min(remaining_size(dev) - (2+1+CMD_FINALIZE_BYTES_NEEDED),
1579 (size_t)(shadow->size - off));
1580 pr_debug("MBR: write bytes %zu+%llu/%llu\n",
1581 off, len, shadow->size);
1582
1583 dst = add_bytestring_header(&err, dev, len);
1584 if (!dst)
1585 break;
1586 if (copy_from_user(dst, src + off, len))
1587 err = -EFAULT;
1588 dev->pos += len;
1589
1590 add_token_u8(&err, dev, OPAL_ENDNAME);
1591 if (err)
1592 break;
1593
1594 err = finalize_and_send(dev, parse_and_check_status);
1595 if (err)
1596 break;
1597
1598 off += len;
1599 }
1600 return err;
1601}
1602
1539static int generic_pw_cmd(u8 *key, size_t key_len, u8 *cpin_uid, 1603static int generic_pw_cmd(u8 *key, size_t key_len, u8 *cpin_uid,
1540 struct opal_dev *dev) 1604 struct opal_dev *dev)
1541{ 1605{
@@ -2013,6 +2077,26 @@ static int opal_set_mbr_done(struct opal_dev *dev,
2013 return ret; 2077 return ret;
2014} 2078}
2015 2079
2080static int opal_write_shadow_mbr(struct opal_dev *dev,
2081 struct opal_shadow_mbr *info)
2082{
2083 const struct opal_step mbr_steps[] = {
2084 { start_admin1LSP_opal_session, &info->key },
2085 { write_shadow_mbr, info },
2086 { end_opal_session, }
2087 };
2088 int ret;
2089
2090 if (info->size == 0)
2091 return 0;
2092
2093 mutex_lock(&dev->dev_lock);
2094 setup_opal_dev(dev);
2095 ret = execute_steps(dev, mbr_steps, ARRAY_SIZE(mbr_steps));
2096 mutex_unlock(&dev->dev_lock);
2097 return ret;
2098}
2099
2016static int opal_save(struct opal_dev *dev, struct opal_lock_unlock *lk_unlk) 2100static int opal_save(struct opal_dev *dev, struct opal_lock_unlock *lk_unlk)
2017{ 2101{
2018 struct opal_suspend_data *suspend; 2102 struct opal_suspend_data *suspend;
@@ -2337,6 +2421,9 @@ int sed_ioctl(struct opal_dev *dev, unsigned int cmd, void __user *arg)
2337 case IOC_OPAL_MBR_DONE: 2421 case IOC_OPAL_MBR_DONE:
2338 ret = opal_set_mbr_done(dev, p); 2422 ret = opal_set_mbr_done(dev, p);
2339 break; 2423 break;
2424 case IOC_OPAL_WRITE_SHADOW_MBR:
2425 ret = opal_write_shadow_mbr(dev, p);
2426 break;
2340 case IOC_OPAL_ERASE_LR: 2427 case IOC_OPAL_ERASE_LR:
2341 ret = opal_erase_locking_range(dev, p); 2428 ret = opal_erase_locking_range(dev, p);
2342 break; 2429 break;