0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/armada-37xx-rwtm-mailbox.h>
0009 #include <linux/completion.h>
0010 #include <linux/debugfs.h>
0011 #include <linux/dma-mapping.h>
0012 #include <linux/hw_random.h>
0013 #include <linux/mailbox_client.h>
0014 #include <linux/module.h>
0015 #include <linux/mutex.h>
0016 #include <linux/of.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/slab.h>
0019
0020 #define DRIVER_NAME "turris-mox-rwtm"
0021
0022
0023
0024
0025
0026
0027
0028 #define MBOX_STS_SUCCESS (0 << 30)
0029 #define MBOX_STS_FAIL (1 << 30)
0030 #define MBOX_STS_BADCMD (2 << 30)
0031 #define MBOX_STS_ERROR(s) ((s) & (3 << 30))
0032 #define MBOX_STS_VALUE(s) (((s) >> 10) & 0xfffff)
0033 #define MBOX_STS_CMD(s) ((s) & 0x3ff)
0034
0035 enum mbox_cmd {
0036 MBOX_CMD_GET_RANDOM = 1,
0037 MBOX_CMD_BOARD_INFO = 2,
0038 MBOX_CMD_ECDSA_PUB_KEY = 3,
0039 MBOX_CMD_HASH = 4,
0040 MBOX_CMD_SIGN = 5,
0041 MBOX_CMD_VERIFY = 6,
0042
0043 MBOX_CMD_OTP_READ = 7,
0044 MBOX_CMD_OTP_WRITE = 8,
0045 };
0046
0047 struct mox_kobject;
0048
0049 struct mox_rwtm {
0050 struct device *dev;
0051 struct mbox_client mbox_client;
0052 struct mbox_chan *mbox;
0053 struct mox_kobject *kobj;
0054 struct hwrng hwrng;
0055
0056 struct armada_37xx_rwtm_rx_msg reply;
0057
0058 void *buf;
0059 dma_addr_t buf_phys;
0060
0061 struct mutex busy;
0062 struct completion cmd_done;
0063
0064
0065 int has_board_info;
0066 u64 serial_number;
0067 int board_version, ram_size;
0068 u8 mac_address1[6], mac_address2[6];
0069
0070
0071 int has_pubkey;
0072 u8 pubkey[135];
0073
0074 #ifdef CONFIG_DEBUG_FS
0075
0076
0077
0078
0079
0080
0081 struct dentry *debugfs_root;
0082 u32 last_sig[34];
0083 int last_sig_done;
0084 #endif
0085 };
0086
0087 struct mox_kobject {
0088 struct kobject kobj;
0089 struct mox_rwtm *rwtm;
0090 };
0091
0092 static inline struct kobject *rwtm_to_kobj(struct mox_rwtm *rwtm)
0093 {
0094 return &rwtm->kobj->kobj;
0095 }
0096
0097 static inline struct mox_rwtm *to_rwtm(struct kobject *kobj)
0098 {
0099 return container_of(kobj, struct mox_kobject, kobj)->rwtm;
0100 }
0101
0102 static void mox_kobj_release(struct kobject *kobj)
0103 {
0104 kfree(to_rwtm(kobj)->kobj);
0105 }
0106
0107 static struct kobj_type mox_kobj_ktype = {
0108 .release = mox_kobj_release,
0109 .sysfs_ops = &kobj_sysfs_ops,
0110 };
0111
0112 static int mox_kobj_create(struct mox_rwtm *rwtm)
0113 {
0114 rwtm->kobj = kzalloc(sizeof(*rwtm->kobj), GFP_KERNEL);
0115 if (!rwtm->kobj)
0116 return -ENOMEM;
0117
0118 kobject_init(rwtm_to_kobj(rwtm), &mox_kobj_ktype);
0119 if (kobject_add(rwtm_to_kobj(rwtm), firmware_kobj, "turris-mox-rwtm")) {
0120 kobject_put(rwtm_to_kobj(rwtm));
0121 return -ENXIO;
0122 }
0123
0124 rwtm->kobj->rwtm = rwtm;
0125
0126 return 0;
0127 }
0128
0129 #define MOX_ATTR_RO(name, format, cat) \
0130 static ssize_t \
0131 name##_show(struct kobject *kobj, struct kobj_attribute *a, \
0132 char *buf) \
0133 { \
0134 struct mox_rwtm *rwtm = to_rwtm(kobj); \
0135 if (!rwtm->has_##cat) \
0136 return -ENODATA; \
0137 return sprintf(buf, format, rwtm->name); \
0138 } \
0139 static struct kobj_attribute mox_attr_##name = __ATTR_RO(name)
0140
0141 MOX_ATTR_RO(serial_number, "%016llX\n", board_info);
0142 MOX_ATTR_RO(board_version, "%i\n", board_info);
0143 MOX_ATTR_RO(ram_size, "%i\n", board_info);
0144 MOX_ATTR_RO(mac_address1, "%pM\n", board_info);
0145 MOX_ATTR_RO(mac_address2, "%pM\n", board_info);
0146 MOX_ATTR_RO(pubkey, "%s\n", pubkey);
0147
0148 static int mox_get_status(enum mbox_cmd cmd, u32 retval)
0149 {
0150 if (MBOX_STS_CMD(retval) != cmd)
0151 return -EIO;
0152 else if (MBOX_STS_ERROR(retval) == MBOX_STS_FAIL)
0153 return -(int)MBOX_STS_VALUE(retval);
0154 else if (MBOX_STS_ERROR(retval) == MBOX_STS_BADCMD)
0155 return -ENOSYS;
0156 else if (MBOX_STS_ERROR(retval) != MBOX_STS_SUCCESS)
0157 return -EIO;
0158 else
0159 return MBOX_STS_VALUE(retval);
0160 }
0161
0162 static const struct attribute *mox_rwtm_attrs[] = {
0163 &mox_attr_serial_number.attr,
0164 &mox_attr_board_version.attr,
0165 &mox_attr_ram_size.attr,
0166 &mox_attr_mac_address1.attr,
0167 &mox_attr_mac_address2.attr,
0168 &mox_attr_pubkey.attr,
0169 NULL
0170 };
0171
0172 static void mox_rwtm_rx_callback(struct mbox_client *cl, void *data)
0173 {
0174 struct mox_rwtm *rwtm = dev_get_drvdata(cl->dev);
0175 struct armada_37xx_rwtm_rx_msg *msg = data;
0176
0177 rwtm->reply = *msg;
0178 complete(&rwtm->cmd_done);
0179 }
0180
0181 static void reply_to_mac_addr(u8 *mac, u32 t1, u32 t2)
0182 {
0183 mac[0] = t1 >> 8;
0184 mac[1] = t1;
0185 mac[2] = t2 >> 24;
0186 mac[3] = t2 >> 16;
0187 mac[4] = t2 >> 8;
0188 mac[5] = t2;
0189 }
0190
0191 static int mox_get_board_info(struct mox_rwtm *rwtm)
0192 {
0193 struct armada_37xx_rwtm_tx_msg msg;
0194 struct armada_37xx_rwtm_rx_msg *reply = &rwtm->reply;
0195 int ret;
0196
0197 msg.command = MBOX_CMD_BOARD_INFO;
0198 ret = mbox_send_message(rwtm->mbox, &msg);
0199 if (ret < 0)
0200 return ret;
0201
0202 ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
0203 if (ret < 0)
0204 return ret;
0205
0206 ret = mox_get_status(MBOX_CMD_BOARD_INFO, reply->retval);
0207 if (ret == -ENODATA) {
0208 dev_warn(rwtm->dev,
0209 "Board does not have manufacturing information burned!\n");
0210 } else if (ret == -ENOSYS) {
0211 dev_notice(rwtm->dev,
0212 "Firmware does not support the BOARD_INFO command\n");
0213 } else if (ret < 0) {
0214 return ret;
0215 } else {
0216 rwtm->serial_number = reply->status[1];
0217 rwtm->serial_number <<= 32;
0218 rwtm->serial_number |= reply->status[0];
0219 rwtm->board_version = reply->status[2];
0220 rwtm->ram_size = reply->status[3];
0221 reply_to_mac_addr(rwtm->mac_address1, reply->status[4],
0222 reply->status[5]);
0223 reply_to_mac_addr(rwtm->mac_address2, reply->status[6],
0224 reply->status[7]);
0225 rwtm->has_board_info = 1;
0226
0227 pr_info("Turris Mox serial number %016llX\n",
0228 rwtm->serial_number);
0229 pr_info(" board version %i\n", rwtm->board_version);
0230 pr_info(" burned RAM size %i MiB\n", rwtm->ram_size);
0231 }
0232
0233 msg.command = MBOX_CMD_ECDSA_PUB_KEY;
0234 ret = mbox_send_message(rwtm->mbox, &msg);
0235 if (ret < 0)
0236 return ret;
0237
0238 ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
0239 if (ret < 0)
0240 return ret;
0241
0242 ret = mox_get_status(MBOX_CMD_ECDSA_PUB_KEY, reply->retval);
0243 if (ret == -ENODATA) {
0244 dev_warn(rwtm->dev, "Board has no public key burned!\n");
0245 } else if (ret == -ENOSYS) {
0246 dev_notice(rwtm->dev,
0247 "Firmware does not support the ECDSA_PUB_KEY command\n");
0248 } else if (ret < 0) {
0249 return ret;
0250 } else {
0251 u32 *s = reply->status;
0252
0253 rwtm->has_pubkey = 1;
0254 sprintf(rwtm->pubkey,
0255 "%06x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x",
0256 ret, s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7],
0257 s[8], s[9], s[10], s[11], s[12], s[13], s[14], s[15]);
0258 }
0259
0260 return 0;
0261 }
0262
0263 static int check_get_random_support(struct mox_rwtm *rwtm)
0264 {
0265 struct armada_37xx_rwtm_tx_msg msg;
0266 int ret;
0267
0268 msg.command = MBOX_CMD_GET_RANDOM;
0269 msg.args[0] = 1;
0270 msg.args[1] = rwtm->buf_phys;
0271 msg.args[2] = 4;
0272
0273 ret = mbox_send_message(rwtm->mbox, &msg);
0274 if (ret < 0)
0275 return ret;
0276
0277 ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
0278 if (ret < 0)
0279 return ret;
0280
0281 return mox_get_status(MBOX_CMD_GET_RANDOM, rwtm->reply.retval);
0282 }
0283
0284 static int mox_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
0285 {
0286 struct mox_rwtm *rwtm = (struct mox_rwtm *) rng->priv;
0287 struct armada_37xx_rwtm_tx_msg msg;
0288 int ret;
0289
0290 if (max > 4096)
0291 max = 4096;
0292
0293 msg.command = MBOX_CMD_GET_RANDOM;
0294 msg.args[0] = 1;
0295 msg.args[1] = rwtm->buf_phys;
0296 msg.args[2] = (max + 3) & ~3;
0297
0298 if (!wait) {
0299 if (!mutex_trylock(&rwtm->busy))
0300 return -EBUSY;
0301 } else {
0302 mutex_lock(&rwtm->busy);
0303 }
0304
0305 ret = mbox_send_message(rwtm->mbox, &msg);
0306 if (ret < 0)
0307 goto unlock_mutex;
0308
0309 ret = wait_for_completion_interruptible(&rwtm->cmd_done);
0310 if (ret < 0)
0311 goto unlock_mutex;
0312
0313 ret = mox_get_status(MBOX_CMD_GET_RANDOM, rwtm->reply.retval);
0314 if (ret < 0)
0315 goto unlock_mutex;
0316
0317 memcpy(data, rwtm->buf, max);
0318 ret = max;
0319
0320 unlock_mutex:
0321 mutex_unlock(&rwtm->busy);
0322 return ret;
0323 }
0324
0325 #ifdef CONFIG_DEBUG_FS
0326 static int rwtm_debug_open(struct inode *inode, struct file *file)
0327 {
0328 file->private_data = inode->i_private;
0329
0330 return nonseekable_open(inode, file);
0331 }
0332
0333 static ssize_t do_sign_read(struct file *file, char __user *buf, size_t len,
0334 loff_t *ppos)
0335 {
0336 struct mox_rwtm *rwtm = file->private_data;
0337 ssize_t ret;
0338
0339
0340 if (*ppos != 0)
0341 return 0;
0342
0343 if (len < 136)
0344 return -EINVAL;
0345
0346 if (!rwtm->last_sig_done)
0347 return -ENODATA;
0348
0349
0350 ret = simple_read_from_buffer(buf, len, ppos, rwtm->last_sig, 136);
0351 rwtm->last_sig_done = 0;
0352
0353 return ret;
0354 }
0355
0356 static ssize_t do_sign_write(struct file *file, const char __user *buf,
0357 size_t len, loff_t *ppos)
0358 {
0359 struct mox_rwtm *rwtm = file->private_data;
0360 struct armada_37xx_rwtm_rx_msg *reply = &rwtm->reply;
0361 struct armada_37xx_rwtm_tx_msg msg;
0362 loff_t dummy = 0;
0363 ssize_t ret;
0364
0365
0366 if (len != 64)
0367 return -EINVAL;
0368
0369
0370 if (rwtm->last_sig_done)
0371 return -EBUSY;
0372
0373 if (!mutex_trylock(&rwtm->busy))
0374 return -EBUSY;
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387 memset(rwtm->buf, 0, 4);
0388 ret = simple_write_to_buffer(rwtm->buf + 4, 64, &dummy, buf, len);
0389 if (ret < 0)
0390 goto unlock_mutex;
0391 be32_to_cpu_array(rwtm->buf, rwtm->buf, 17);
0392
0393 msg.command = MBOX_CMD_SIGN;
0394 msg.args[0] = 1;
0395 msg.args[1] = rwtm->buf_phys;
0396 msg.args[2] = rwtm->buf_phys + 68;
0397 msg.args[3] = rwtm->buf_phys + 2 * 68;
0398 ret = mbox_send_message(rwtm->mbox, &msg);
0399 if (ret < 0)
0400 goto unlock_mutex;
0401
0402 ret = wait_for_completion_interruptible(&rwtm->cmd_done);
0403 if (ret < 0)
0404 goto unlock_mutex;
0405
0406 ret = MBOX_STS_VALUE(reply->retval);
0407 if (MBOX_STS_ERROR(reply->retval) != MBOX_STS_SUCCESS)
0408 goto unlock_mutex;
0409
0410
0411
0412
0413
0414
0415 memcpy(rwtm->last_sig, rwtm->buf + 68, 136);
0416 cpu_to_be32_array(rwtm->last_sig, rwtm->last_sig, 34);
0417 rwtm->last_sig_done = 1;
0418
0419 mutex_unlock(&rwtm->busy);
0420 return len;
0421 unlock_mutex:
0422 mutex_unlock(&rwtm->busy);
0423 return ret;
0424 }
0425
0426 static const struct file_operations do_sign_fops = {
0427 .owner = THIS_MODULE,
0428 .open = rwtm_debug_open,
0429 .read = do_sign_read,
0430 .write = do_sign_write,
0431 .llseek = no_llseek,
0432 };
0433
0434 static int rwtm_register_debugfs(struct mox_rwtm *rwtm)
0435 {
0436 struct dentry *root, *entry;
0437
0438 root = debugfs_create_dir("turris-mox-rwtm", NULL);
0439
0440 if (IS_ERR(root))
0441 return PTR_ERR(root);
0442
0443 entry = debugfs_create_file_unsafe("do_sign", 0600, root, rwtm,
0444 &do_sign_fops);
0445 if (IS_ERR(entry))
0446 goto err_remove;
0447
0448 rwtm->debugfs_root = root;
0449
0450 return 0;
0451 err_remove:
0452 debugfs_remove_recursive(root);
0453 return PTR_ERR(entry);
0454 }
0455
0456 static void rwtm_unregister_debugfs(struct mox_rwtm *rwtm)
0457 {
0458 debugfs_remove_recursive(rwtm->debugfs_root);
0459 }
0460 #else
0461 static inline int rwtm_register_debugfs(struct mox_rwtm *rwtm)
0462 {
0463 return 0;
0464 }
0465
0466 static inline void rwtm_unregister_debugfs(struct mox_rwtm *rwtm)
0467 {
0468 }
0469 #endif
0470
0471 static int turris_mox_rwtm_probe(struct platform_device *pdev)
0472 {
0473 struct mox_rwtm *rwtm;
0474 struct device *dev = &pdev->dev;
0475 int ret;
0476
0477 rwtm = devm_kzalloc(dev, sizeof(*rwtm), GFP_KERNEL);
0478 if (!rwtm)
0479 return -ENOMEM;
0480
0481 rwtm->dev = dev;
0482 rwtm->buf = dmam_alloc_coherent(dev, PAGE_SIZE, &rwtm->buf_phys,
0483 GFP_KERNEL);
0484 if (!rwtm->buf)
0485 return -ENOMEM;
0486
0487 ret = mox_kobj_create(rwtm);
0488 if (ret < 0) {
0489 dev_err(dev, "Cannot create turris-mox-rwtm kobject!\n");
0490 return ret;
0491 }
0492
0493 ret = sysfs_create_files(rwtm_to_kobj(rwtm), mox_rwtm_attrs);
0494 if (ret < 0) {
0495 dev_err(dev, "Cannot create sysfs files!\n");
0496 goto put_kobj;
0497 }
0498
0499 platform_set_drvdata(pdev, rwtm);
0500
0501 mutex_init(&rwtm->busy);
0502
0503 rwtm->mbox_client.dev = dev;
0504 rwtm->mbox_client.rx_callback = mox_rwtm_rx_callback;
0505
0506 rwtm->mbox = mbox_request_channel(&rwtm->mbox_client, 0);
0507 if (IS_ERR(rwtm->mbox)) {
0508 ret = PTR_ERR(rwtm->mbox);
0509 if (ret != -EPROBE_DEFER)
0510 dev_err(dev, "Cannot request mailbox channel: %i\n",
0511 ret);
0512 goto remove_files;
0513 }
0514
0515 init_completion(&rwtm->cmd_done);
0516
0517 ret = mox_get_board_info(rwtm);
0518 if (ret < 0)
0519 dev_warn(dev, "Cannot read board information: %i\n", ret);
0520
0521 ret = check_get_random_support(rwtm);
0522 if (ret < 0) {
0523 dev_notice(dev,
0524 "Firmware does not support the GET_RANDOM command\n");
0525 goto free_channel;
0526 }
0527
0528 rwtm->hwrng.name = DRIVER_NAME "_hwrng";
0529 rwtm->hwrng.read = mox_hwrng_read;
0530 rwtm->hwrng.priv = (unsigned long) rwtm;
0531 rwtm->hwrng.quality = 1024;
0532
0533 ret = devm_hwrng_register(dev, &rwtm->hwrng);
0534 if (ret < 0) {
0535 dev_err(dev, "Cannot register HWRNG: %i\n", ret);
0536 goto free_channel;
0537 }
0538
0539 ret = rwtm_register_debugfs(rwtm);
0540 if (ret < 0) {
0541 dev_err(dev, "Failed creating debugfs entries: %i\n", ret);
0542 goto free_channel;
0543 }
0544
0545 dev_info(dev, "HWRNG successfully registered\n");
0546
0547 return 0;
0548
0549 free_channel:
0550 mbox_free_channel(rwtm->mbox);
0551 remove_files:
0552 sysfs_remove_files(rwtm_to_kobj(rwtm), mox_rwtm_attrs);
0553 put_kobj:
0554 kobject_put(rwtm_to_kobj(rwtm));
0555 return ret;
0556 }
0557
0558 static int turris_mox_rwtm_remove(struct platform_device *pdev)
0559 {
0560 struct mox_rwtm *rwtm = platform_get_drvdata(pdev);
0561
0562 rwtm_unregister_debugfs(rwtm);
0563 sysfs_remove_files(rwtm_to_kobj(rwtm), mox_rwtm_attrs);
0564 kobject_put(rwtm_to_kobj(rwtm));
0565 mbox_free_channel(rwtm->mbox);
0566
0567 return 0;
0568 }
0569
0570 static const struct of_device_id turris_mox_rwtm_match[] = {
0571 { .compatible = "cznic,turris-mox-rwtm", },
0572 { .compatible = "marvell,armada-3700-rwtm-firmware", },
0573 { },
0574 };
0575
0576 MODULE_DEVICE_TABLE(of, turris_mox_rwtm_match);
0577
0578 static struct platform_driver turris_mox_rwtm_driver = {
0579 .probe = turris_mox_rwtm_probe,
0580 .remove = turris_mox_rwtm_remove,
0581 .driver = {
0582 .name = DRIVER_NAME,
0583 .of_match_table = turris_mox_rwtm_match,
0584 },
0585 };
0586 module_platform_driver(turris_mox_rwtm_driver);
0587
0588 MODULE_LICENSE("GPL v2");
0589 MODULE_DESCRIPTION("Turris Mox rWTM firmware driver");
0590 MODULE_AUTHOR("Marek Behun <kabel@kernel.org>");