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

block: sed-opal: Generalizing write data to any opal table

This patch refactors the existing "write_shadowmbr" func and
creates a new generalized function "generic_table_write_data",
to write data to any opal table. Also, a few cleanups are included
in this patch.

Reviewed-by: Scott Bauer <sbauer@plzdonthack.me>
Reviewed-by: Jon Derrick <jonathan.derrick@intel.com>
Signed-off-by: Revanth Rajashekar <revanth.rajashekar@intel.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Revanth Rajashekar and committed by
Jens Axboe
3495ea1b cba22d86

+74 -64
+74 -64
block/sed-opal.c
··· 1139 1139 * 1140 1140 * the result is provided in dev->resp->tok[4] 1141 1141 */ 1142 - static int generic_get_table_info(struct opal_dev *dev, enum opal_uid table, 1142 + static int generic_get_table_info(struct opal_dev *dev, const u8 *table_uid, 1143 1143 u64 column) 1144 1144 { 1145 1145 u8 uid[OPAL_UID_LENGTH]; 1146 - const unsigned int half = OPAL_UID_LENGTH/2; 1146 + const unsigned int half = OPAL_UID_LENGTH_HALF; 1147 1147 1148 1148 /* sed-opal UIDs can be split in two halves: 1149 1149 * first: actual table index ··· 1152 1152 * first part of the target table as relative index into that table 1153 1153 */ 1154 1154 memcpy(uid, opaluid[OPAL_TABLE_TABLE], half); 1155 - memcpy(uid+half, opaluid[table], half); 1155 + memcpy(uid + half, table_uid, half); 1156 1156 1157 1157 return generic_get_column(dev, uid, column); 1158 1158 } ··· 1219 1219 return err; 1220 1220 1221 1221 return get_active_key_cont(dev); 1222 + } 1223 + 1224 + static int generic_table_write_data(struct opal_dev *dev, const u64 data, 1225 + u64 offset, u64 size, const u8 *uid) 1226 + { 1227 + const u8 __user *src = (u8 __user *)(uintptr_t)data; 1228 + u8 *dst; 1229 + u64 len; 1230 + size_t off = 0; 1231 + int err; 1232 + 1233 + /* do we fit in the available space? */ 1234 + err = generic_get_table_info(dev, uid, OPAL_TABLE_ROWS); 1235 + if (err) { 1236 + pr_debug("Couldn't get the table size\n"); 1237 + return err; 1238 + } 1239 + 1240 + len = response_get_u64(&dev->parsed, 4); 1241 + if (size > len || offset > len - size) { 1242 + pr_debug("Does not fit in the table (%llu vs. %llu)\n", 1243 + offset + size, len); 1244 + return -ENOSPC; 1245 + } 1246 + 1247 + /* do the actual transmission(s) */ 1248 + while (off < size) { 1249 + err = cmd_start(dev, uid, opalmethod[OPAL_SET]); 1250 + add_token_u8(&err, dev, OPAL_STARTNAME); 1251 + add_token_u8(&err, dev, OPAL_WHERE); 1252 + add_token_u64(&err, dev, offset + off); 1253 + add_token_u8(&err, dev, OPAL_ENDNAME); 1254 + 1255 + add_token_u8(&err, dev, OPAL_STARTNAME); 1256 + add_token_u8(&err, dev, OPAL_VALUES); 1257 + 1258 + /* 1259 + * The bytestring header is either 1 or 2 bytes, so assume 2. 1260 + * There also needs to be enough space to accommodate the 1261 + * trailing OPAL_ENDNAME (1 byte) and tokens added by 1262 + * cmd_finalize. 1263 + */ 1264 + len = min(remaining_size(dev) - (2+1+CMD_FINALIZE_BYTES_NEEDED), 1265 + (size_t)(size - off)); 1266 + pr_debug("Write bytes %zu+%llu/%llu\n", off, len, size); 1267 + 1268 + dst = add_bytestring_header(&err, dev, len); 1269 + if (!dst) 1270 + break; 1271 + 1272 + if (copy_from_user(dst, src + off, len)) { 1273 + err = -EFAULT; 1274 + break; 1275 + } 1276 + 1277 + dev->pos += len; 1278 + 1279 + add_token_u8(&err, dev, OPAL_ENDNAME); 1280 + if (err) 1281 + break; 1282 + 1283 + err = finalize_and_send(dev, parse_and_check_status); 1284 + if (err) 1285 + break; 1286 + 1287 + off += len; 1288 + } 1289 + 1290 + return err; 1222 1291 } 1223 1292 1224 1293 static int generic_lr_enable_disable(struct opal_dev *dev, ··· 1652 1583 static int write_shadow_mbr(struct opal_dev *dev, void *data) 1653 1584 { 1654 1585 struct opal_shadow_mbr *shadow = data; 1655 - const u8 __user *src; 1656 - u8 *dst; 1657 - size_t off = 0; 1658 - u64 len; 1659 - int err = 0; 1660 1586 1661 - /* do we fit in the available shadow mbr space? */ 1662 - err = generic_get_table_info(dev, OPAL_MBR, OPAL_TABLE_ROWS); 1663 - if (err) { 1664 - pr_debug("MBR: could not get shadow size\n"); 1665 - return err; 1666 - } 1667 - 1668 - len = response_get_u64(&dev->parsed, 4); 1669 - if (shadow->size > len || shadow->offset > len - shadow->size) { 1670 - pr_debug("MBR: does not fit in shadow (%llu vs. %llu)\n", 1671 - shadow->offset + shadow->size, len); 1672 - return -ENOSPC; 1673 - } 1674 - 1675 - /* do the actual transmission(s) */ 1676 - src = (u8 __user *)(uintptr_t)shadow->data; 1677 - while (off < shadow->size) { 1678 - err = cmd_start(dev, opaluid[OPAL_MBR], opalmethod[OPAL_SET]); 1679 - add_token_u8(&err, dev, OPAL_STARTNAME); 1680 - add_token_u8(&err, dev, OPAL_WHERE); 1681 - add_token_u64(&err, dev, shadow->offset + off); 1682 - add_token_u8(&err, dev, OPAL_ENDNAME); 1683 - 1684 - add_token_u8(&err, dev, OPAL_STARTNAME); 1685 - add_token_u8(&err, dev, OPAL_VALUES); 1686 - 1687 - /* 1688 - * The bytestring header is either 1 or 2 bytes, so assume 2. 1689 - * There also needs to be enough space to accommodate the 1690 - * trailing OPAL_ENDNAME (1 byte) and tokens added by 1691 - * cmd_finalize. 1692 - */ 1693 - len = min(remaining_size(dev) - (2+1+CMD_FINALIZE_BYTES_NEEDED), 1694 - (size_t)(shadow->size - off)); 1695 - pr_debug("MBR: write bytes %zu+%llu/%llu\n", 1696 - off, len, shadow->size); 1697 - 1698 - dst = add_bytestring_header(&err, dev, len); 1699 - if (!dst) 1700 - break; 1701 - if (copy_from_user(dst, src + off, len)) 1702 - err = -EFAULT; 1703 - dev->pos += len; 1704 - 1705 - add_token_u8(&err, dev, OPAL_ENDNAME); 1706 - if (err) 1707 - break; 1708 - 1709 - err = finalize_and_send(dev, parse_and_check_status); 1710 - if (err) 1711 - break; 1712 - 1713 - off += len; 1714 - } 1715 - 1716 - return err; 1587 + return generic_table_write_data(dev, shadow->data, shadow->offset, 1588 + shadow->size, opaluid[OPAL_MBR]); 1717 1589 } 1718 1590 1719 1591 static int generic_pw_cmd(u8 *key, size_t key_len, u8 *cpin_uid,