0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/completion.h>
0010 #include <linux/firmware.h>
0011 #include <crypto/hash.h>
0012 #include <crypto/sha1.h>
0013
0014 #include "s3fwrn5.h"
0015 #include "firmware.h"
0016
0017 struct s3fwrn5_fw_version {
0018 __u8 major;
0019 __u8 build1;
0020 __u8 build2;
0021 __u8 target;
0022 };
0023
0024 static int s3fwrn5_fw_send_msg(struct s3fwrn5_fw_info *fw_info,
0025 struct sk_buff *msg, struct sk_buff **rsp)
0026 {
0027 struct s3fwrn5_info *info =
0028 container_of(fw_info, struct s3fwrn5_info, fw_info);
0029 long ret;
0030
0031 reinit_completion(&fw_info->completion);
0032
0033 ret = s3fwrn5_write(info, msg);
0034 if (ret < 0)
0035 return ret;
0036
0037 ret = wait_for_completion_interruptible_timeout(
0038 &fw_info->completion, msecs_to_jiffies(1000));
0039 if (ret < 0)
0040 return ret;
0041 else if (ret == 0)
0042 return -ENXIO;
0043
0044 if (!fw_info->rsp)
0045 return -EINVAL;
0046
0047 *rsp = fw_info->rsp;
0048 fw_info->rsp = NULL;
0049
0050 return 0;
0051 }
0052
0053 static int s3fwrn5_fw_prep_msg(struct s3fwrn5_fw_info *fw_info,
0054 struct sk_buff **msg, u8 type, u8 code, const void *data, u16 len)
0055 {
0056 struct s3fwrn5_fw_header hdr;
0057 struct sk_buff *skb;
0058
0059 hdr.type = type | fw_info->parity;
0060 fw_info->parity ^= 0x80;
0061 hdr.code = code;
0062 hdr.len = len;
0063
0064 skb = alloc_skb(S3FWRN5_FW_HDR_SIZE + len, GFP_KERNEL);
0065 if (!skb)
0066 return -ENOMEM;
0067
0068 skb_put_data(skb, &hdr, S3FWRN5_FW_HDR_SIZE);
0069 if (len)
0070 skb_put_data(skb, data, len);
0071
0072 *msg = skb;
0073
0074 return 0;
0075 }
0076
0077 static int s3fwrn5_fw_get_bootinfo(struct s3fwrn5_fw_info *fw_info,
0078 struct s3fwrn5_fw_cmd_get_bootinfo_rsp *bootinfo)
0079 {
0080 struct sk_buff *msg, *rsp = NULL;
0081 struct s3fwrn5_fw_header *hdr;
0082 int ret;
0083
0084
0085
0086 ret = s3fwrn5_fw_prep_msg(fw_info, &msg, S3FWRN5_FW_MSG_CMD,
0087 S3FWRN5_FW_CMD_GET_BOOTINFO, NULL, 0);
0088 if (ret < 0)
0089 return ret;
0090
0091 ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp);
0092 kfree_skb(msg);
0093 if (ret < 0)
0094 return ret;
0095
0096 hdr = (struct s3fwrn5_fw_header *) rsp->data;
0097 if (hdr->code != S3FWRN5_FW_RET_SUCCESS) {
0098 ret = -EINVAL;
0099 goto out;
0100 }
0101
0102 memcpy(bootinfo, rsp->data + S3FWRN5_FW_HDR_SIZE, 10);
0103
0104 out:
0105 kfree_skb(rsp);
0106 return ret;
0107 }
0108
0109 static int s3fwrn5_fw_enter_update_mode(struct s3fwrn5_fw_info *fw_info,
0110 const void *hash_data, u16 hash_size,
0111 const void *sig_data, u16 sig_size)
0112 {
0113 struct s3fwrn5_fw_cmd_enter_updatemode args;
0114 struct sk_buff *msg, *rsp = NULL;
0115 struct s3fwrn5_fw_header *hdr;
0116 int ret;
0117
0118
0119
0120 args.hashcode_size = hash_size;
0121 args.signature_size = sig_size;
0122
0123 ret = s3fwrn5_fw_prep_msg(fw_info, &msg, S3FWRN5_FW_MSG_CMD,
0124 S3FWRN5_FW_CMD_ENTER_UPDATE_MODE, &args, sizeof(args));
0125 if (ret < 0)
0126 return ret;
0127
0128 ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp);
0129 kfree_skb(msg);
0130 if (ret < 0)
0131 return ret;
0132
0133 hdr = (struct s3fwrn5_fw_header *) rsp->data;
0134 if (hdr->code != S3FWRN5_FW_RET_SUCCESS) {
0135 ret = -EPROTO;
0136 goto out;
0137 }
0138
0139 kfree_skb(rsp);
0140
0141
0142
0143 ret = s3fwrn5_fw_prep_msg(fw_info, &msg, S3FWRN5_FW_MSG_DATA, 0,
0144 hash_data, hash_size);
0145 if (ret < 0)
0146 return ret;
0147
0148 ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp);
0149 kfree_skb(msg);
0150 if (ret < 0)
0151 return ret;
0152
0153 hdr = (struct s3fwrn5_fw_header *) rsp->data;
0154 if (hdr->code != S3FWRN5_FW_RET_SUCCESS) {
0155 ret = -EPROTO;
0156 goto out;
0157 }
0158
0159 kfree_skb(rsp);
0160
0161
0162
0163 ret = s3fwrn5_fw_prep_msg(fw_info, &msg, S3FWRN5_FW_MSG_DATA, 0,
0164 sig_data, sig_size);
0165 if (ret < 0)
0166 return ret;
0167
0168 ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp);
0169 kfree_skb(msg);
0170 if (ret < 0)
0171 return ret;
0172
0173 hdr = (struct s3fwrn5_fw_header *) rsp->data;
0174 if (hdr->code != S3FWRN5_FW_RET_SUCCESS)
0175 ret = -EPROTO;
0176
0177 out:
0178 kfree_skb(rsp);
0179 return ret;
0180 }
0181
0182 static int s3fwrn5_fw_update_sector(struct s3fwrn5_fw_info *fw_info,
0183 u32 base_addr, const void *data)
0184 {
0185 struct s3fwrn5_fw_cmd_update_sector args;
0186 struct sk_buff *msg, *rsp = NULL;
0187 struct s3fwrn5_fw_header *hdr;
0188 int ret, i;
0189
0190
0191
0192 args.base_address = base_addr;
0193
0194 ret = s3fwrn5_fw_prep_msg(fw_info, &msg, S3FWRN5_FW_MSG_CMD,
0195 S3FWRN5_FW_CMD_UPDATE_SECTOR, &args, sizeof(args));
0196 if (ret < 0)
0197 return ret;
0198
0199 ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp);
0200 kfree_skb(msg);
0201 if (ret < 0)
0202 return ret;
0203
0204 hdr = (struct s3fwrn5_fw_header *) rsp->data;
0205 if (hdr->code != S3FWRN5_FW_RET_SUCCESS) {
0206 ret = -EPROTO;
0207 goto err;
0208 }
0209
0210 kfree_skb(rsp);
0211
0212
0213
0214 for (i = 0; i < 16; ++i) {
0215 ret = s3fwrn5_fw_prep_msg(fw_info, &msg,
0216 S3FWRN5_FW_MSG_DATA, 0, data+256*i, 256);
0217 if (ret < 0)
0218 break;
0219
0220 ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp);
0221 kfree_skb(msg);
0222 if (ret < 0)
0223 break;
0224
0225 hdr = (struct s3fwrn5_fw_header *) rsp->data;
0226 if (hdr->code != S3FWRN5_FW_RET_SUCCESS) {
0227 ret = -EPROTO;
0228 goto err;
0229 }
0230
0231 kfree_skb(rsp);
0232 }
0233
0234 return ret;
0235
0236 err:
0237 kfree_skb(rsp);
0238 return ret;
0239 }
0240
0241 static int s3fwrn5_fw_complete_update_mode(struct s3fwrn5_fw_info *fw_info)
0242 {
0243 struct sk_buff *msg, *rsp = NULL;
0244 struct s3fwrn5_fw_header *hdr;
0245 int ret;
0246
0247
0248
0249 ret = s3fwrn5_fw_prep_msg(fw_info, &msg, S3FWRN5_FW_MSG_CMD,
0250 S3FWRN5_FW_CMD_COMPLETE_UPDATE_MODE, NULL, 0);
0251 if (ret < 0)
0252 return ret;
0253
0254 ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp);
0255 kfree_skb(msg);
0256 if (ret < 0)
0257 return ret;
0258
0259 hdr = (struct s3fwrn5_fw_header *) rsp->data;
0260 if (hdr->code != S3FWRN5_FW_RET_SUCCESS)
0261 ret = -EPROTO;
0262
0263 kfree_skb(rsp);
0264
0265 return ret;
0266 }
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281 #define S3FWRN5_FW_IMAGE_HEADER_SIZE 44
0282
0283 int s3fwrn5_fw_request_firmware(struct s3fwrn5_fw_info *fw_info)
0284 {
0285 struct s3fwrn5_fw_image *fw = &fw_info->fw;
0286 u32 sig_off;
0287 u32 image_off;
0288 u32 custom_sig_off;
0289 int ret;
0290
0291 ret = request_firmware(&fw->fw, fw_info->fw_name,
0292 &fw_info->ndev->nfc_dev->dev);
0293 if (ret < 0)
0294 return ret;
0295
0296 if (fw->fw->size < S3FWRN5_FW_IMAGE_HEADER_SIZE) {
0297 release_firmware(fw->fw);
0298 return -EINVAL;
0299 }
0300
0301 memcpy(fw->date, fw->fw->data + 0x00, 12);
0302 fw->date[12] = '\0';
0303
0304 memcpy(&fw->version, fw->fw->data + 0x10, 4);
0305
0306 memcpy(&sig_off, fw->fw->data + 0x14, 4);
0307 fw->sig = fw->fw->data + sig_off;
0308 memcpy(&fw->sig_size, fw->fw->data + 0x18, 4);
0309
0310 memcpy(&image_off, fw->fw->data + 0x1C, 4);
0311 fw->image = fw->fw->data + image_off;
0312 memcpy(&fw->image_sectors, fw->fw->data + 0x20, 4);
0313
0314 memcpy(&custom_sig_off, fw->fw->data + 0x24, 4);
0315 fw->custom_sig = fw->fw->data + custom_sig_off;
0316 memcpy(&fw->custom_sig_size, fw->fw->data + 0x28, 4);
0317
0318 return 0;
0319 }
0320
0321 static void s3fwrn5_fw_release_firmware(struct s3fwrn5_fw_info *fw_info)
0322 {
0323 release_firmware(fw_info->fw.fw);
0324 }
0325
0326 static int s3fwrn5_fw_get_base_addr(
0327 struct s3fwrn5_fw_cmd_get_bootinfo_rsp *bootinfo, u32 *base_addr)
0328 {
0329 int i;
0330 static const struct {
0331 u8 version[4];
0332 u32 base_addr;
0333 } match[] = {
0334 {{0x05, 0x00, 0x00, 0x00}, 0x00005000},
0335 {{0x05, 0x00, 0x00, 0x01}, 0x00003000},
0336 {{0x05, 0x00, 0x00, 0x02}, 0x00003000},
0337 {{0x05, 0x00, 0x00, 0x03}, 0x00003000},
0338 {{0x05, 0x00, 0x00, 0x05}, 0x00003000}
0339 };
0340
0341 for (i = 0; i < ARRAY_SIZE(match); ++i)
0342 if (bootinfo->hw_version[0] == match[i].version[0] &&
0343 bootinfo->hw_version[1] == match[i].version[1] &&
0344 bootinfo->hw_version[3] == match[i].version[3]) {
0345 *base_addr = match[i].base_addr;
0346 return 0;
0347 }
0348
0349 return -EINVAL;
0350 }
0351
0352 static inline bool
0353 s3fwrn5_fw_is_custom(const struct s3fwrn5_fw_cmd_get_bootinfo_rsp *bootinfo)
0354 {
0355 return !!bootinfo->hw_version[2];
0356 }
0357
0358 int s3fwrn5_fw_setup(struct s3fwrn5_fw_info *fw_info)
0359 {
0360 struct device *dev = &fw_info->ndev->nfc_dev->dev;
0361 struct s3fwrn5_fw_cmd_get_bootinfo_rsp bootinfo;
0362 int ret;
0363
0364
0365
0366 ret = s3fwrn5_fw_get_bootinfo(fw_info, &bootinfo);
0367 if (ret < 0) {
0368 dev_err(dev, "Failed to get bootinfo, ret=%02x\n", ret);
0369 goto err;
0370 }
0371
0372
0373
0374 ret = s3fwrn5_fw_get_base_addr(&bootinfo, &fw_info->base_addr);
0375 if (ret < 0) {
0376 dev_err(dev, "Unknown hardware version\n");
0377 goto err;
0378 }
0379
0380 fw_info->sector_size = bootinfo.sector_size;
0381
0382 fw_info->sig_size = s3fwrn5_fw_is_custom(&bootinfo) ?
0383 fw_info->fw.custom_sig_size : fw_info->fw.sig_size;
0384 fw_info->sig = s3fwrn5_fw_is_custom(&bootinfo) ?
0385 fw_info->fw.custom_sig : fw_info->fw.sig;
0386
0387 return 0;
0388
0389 err:
0390 s3fwrn5_fw_release_firmware(fw_info);
0391 return ret;
0392 }
0393
0394 bool s3fwrn5_fw_check_version(const struct s3fwrn5_fw_info *fw_info, u32 version)
0395 {
0396 struct s3fwrn5_fw_version *new = (void *) &fw_info->fw.version;
0397 struct s3fwrn5_fw_version *old = (void *) &version;
0398
0399 if (new->major > old->major)
0400 return true;
0401 if (new->build1 > old->build1)
0402 return true;
0403 if (new->build2 > old->build2)
0404 return true;
0405
0406 return false;
0407 }
0408
0409 int s3fwrn5_fw_download(struct s3fwrn5_fw_info *fw_info)
0410 {
0411 struct device *dev = &fw_info->ndev->nfc_dev->dev;
0412 struct s3fwrn5_fw_image *fw = &fw_info->fw;
0413 u8 hash_data[SHA1_DIGEST_SIZE];
0414 struct crypto_shash *tfm;
0415 u32 image_size, off;
0416 int ret;
0417
0418 image_size = fw_info->sector_size * fw->image_sectors;
0419
0420
0421
0422 tfm = crypto_alloc_shash("sha1", 0, 0);
0423 if (IS_ERR(tfm)) {
0424 dev_err(dev, "Cannot allocate shash (code=%pe)\n", tfm);
0425 return PTR_ERR(tfm);
0426 }
0427
0428 ret = crypto_shash_tfm_digest(tfm, fw->image, image_size, hash_data);
0429
0430 crypto_free_shash(tfm);
0431 if (ret) {
0432 dev_err(dev, "Cannot compute hash (code=%d)\n", ret);
0433 return ret;
0434 }
0435
0436
0437
0438 dev_info(dev, "Firmware update: %s\n", fw_info->fw_name);
0439
0440 ret = s3fwrn5_fw_enter_update_mode(fw_info, hash_data,
0441 SHA1_DIGEST_SIZE, fw_info->sig, fw_info->sig_size);
0442 if (ret < 0) {
0443 dev_err(dev, "Unable to enter update mode\n");
0444 return ret;
0445 }
0446
0447 for (off = 0; off < image_size; off += fw_info->sector_size) {
0448 ret = s3fwrn5_fw_update_sector(fw_info,
0449 fw_info->base_addr + off, fw->image + off);
0450 if (ret < 0) {
0451 dev_err(dev, "Firmware update error (code=%d)\n", ret);
0452 return ret;
0453 }
0454 }
0455
0456 ret = s3fwrn5_fw_complete_update_mode(fw_info);
0457 if (ret < 0) {
0458 dev_err(dev, "Unable to complete update mode\n");
0459 return ret;
0460 }
0461
0462 dev_info(dev, "Firmware update: success\n");
0463
0464 return ret;
0465 }
0466
0467 void s3fwrn5_fw_init(struct s3fwrn5_fw_info *fw_info, const char *fw_name)
0468 {
0469 fw_info->parity = 0x00;
0470 fw_info->rsp = NULL;
0471 fw_info->fw.fw = NULL;
0472 strcpy(fw_info->fw_name, fw_name);
0473 init_completion(&fw_info->completion);
0474 }
0475
0476 void s3fwrn5_fw_cleanup(struct s3fwrn5_fw_info *fw_info)
0477 {
0478 s3fwrn5_fw_release_firmware(fw_info);
0479 }
0480
0481 int s3fwrn5_fw_recv_frame(struct nci_dev *ndev, struct sk_buff *skb)
0482 {
0483 struct s3fwrn5_info *info = nci_get_drvdata(ndev);
0484 struct s3fwrn5_fw_info *fw_info = &info->fw_info;
0485
0486 if (WARN_ON(fw_info->rsp)) {
0487 kfree_skb(skb);
0488 return -EINVAL;
0489 }
0490
0491 fw_info->rsp = skb;
0492
0493 complete(&fw_info->completion);
0494
0495 return 0;
0496 }