1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * NCI based driver for Samsung S3FWRN5 NFC chip 4 * 5 * Copyright (C) 2015 Samsung Electrnoics 6 * Robert Baldyga <r.baldyga@samsung.com> 7 */ 8 9 #include <linux/completion.h> 10 #include <linux/firmware.h> 11 #include <crypto/hash.h> 12 #include <crypto/sha.h> 13 14 #include "s3fwrn5.h" 15 #include "firmware.h" 16 17 struct s3fwrn5_fw_version { 18 __u8 major; 19 __u8 build1; 20 __u8 build2; 21 __u8 target; 22 }; 23 24 static int s3fwrn5_fw_send_msg(struct s3fwrn5_fw_info *fw_info, 25 struct sk_buff *msg, struct sk_buff **rsp) 26 { 27 struct s3fwrn5_info *info = 28 container_of(fw_info, struct s3fwrn5_info, fw_info); 29 long ret; 30 31 reinit_completion(&fw_info->completion); 32 33 ret = s3fwrn5_write(info, msg); 34 if (ret < 0) 35 return ret; 36 37 ret = wait_for_completion_interruptible_timeout( 38 &fw_info->completion, msecs_to_jiffies(1000)); 39 if (ret < 0) 40 return ret; 41 else if (ret == 0) 42 return -ENXIO; 43 44 if (!fw_info->rsp) 45 return -EINVAL; 46 47 *rsp = fw_info->rsp; 48 fw_info->rsp = NULL; 49 50 return 0; 51 } 52 53 static int s3fwrn5_fw_prep_msg(struct s3fwrn5_fw_info *fw_info, 54 struct sk_buff **msg, u8 type, u8 code, const void *data, u16 len) 55 { 56 struct s3fwrn5_fw_header hdr; 57 struct sk_buff *skb; 58 59 hdr.type = type | fw_info->parity; 60 fw_info->parity ^= 0x80; 61 hdr.code = code; 62 hdr.len = len; 63 64 skb = alloc_skb(S3FWRN5_FW_HDR_SIZE + len, GFP_KERNEL); 65 if (!skb) 66 return -ENOMEM; 67 68 skb_put_data(skb, &hdr, S3FWRN5_FW_HDR_SIZE); 69 if (len) 70 skb_put_data(skb, data, len); 71 72 *msg = skb; 73 74 return 0; 75 } 76 77 static int s3fwrn5_fw_get_bootinfo(struct s3fwrn5_fw_info *fw_info, 78 struct s3fwrn5_fw_cmd_get_bootinfo_rsp *bootinfo) 79 { 80 struct sk_buff *msg, *rsp = NULL; 81 struct s3fwrn5_fw_header *hdr; 82 int ret; 83 84 /* Send GET_BOOTINFO command */ 85 86 ret = s3fwrn5_fw_prep_msg(fw_info, &msg, S3FWRN5_FW_MSG_CMD, 87 S3FWRN5_FW_CMD_GET_BOOTINFO, NULL, 0); 88 if (ret < 0) 89 return ret; 90 91 ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp); 92 kfree_skb(msg); 93 if (ret < 0) 94 return ret; 95 96 hdr = (struct s3fwrn5_fw_header *) rsp->data; 97 if (hdr->code != S3FWRN5_FW_RET_SUCCESS) { 98 ret = -EINVAL; 99 goto out; 100 } 101 102 memcpy(bootinfo, rsp->data + S3FWRN5_FW_HDR_SIZE, 10); 103 104 out: 105 kfree_skb(rsp); 106 return ret; 107 } 108 109 static int s3fwrn5_fw_enter_update_mode(struct s3fwrn5_fw_info *fw_info, 110 const void *hash_data, u16 hash_size, 111 const void *sig_data, u16 sig_size) 112 { 113 struct s3fwrn5_fw_cmd_enter_updatemode args; 114 struct sk_buff *msg, *rsp = NULL; 115 struct s3fwrn5_fw_header *hdr; 116 int ret; 117 118 /* Send ENTER_UPDATE_MODE command */ 119 120 args.hashcode_size = hash_size; 121 args.signature_size = sig_size; 122 123 ret = s3fwrn5_fw_prep_msg(fw_info, &msg, S3FWRN5_FW_MSG_CMD, 124 S3FWRN5_FW_CMD_ENTER_UPDATE_MODE, &args, sizeof(args)); 125 if (ret < 0) 126 return ret; 127 128 ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp); 129 kfree_skb(msg); 130 if (ret < 0) 131 return ret; 132 133 hdr = (struct s3fwrn5_fw_header *) rsp->data; 134 if (hdr->code != S3FWRN5_FW_RET_SUCCESS) { 135 ret = -EPROTO; 136 goto out; 137 } 138 139 kfree_skb(rsp); 140 141 /* Send hashcode data */ 142 143 ret = s3fwrn5_fw_prep_msg(fw_info, &msg, S3FWRN5_FW_MSG_DATA, 0, 144 hash_data, hash_size); 145 if (ret < 0) 146 return ret; 147 148 ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp); 149 kfree_skb(msg); 150 if (ret < 0) 151 return ret; 152 153 hdr = (struct s3fwrn5_fw_header *) rsp->data; 154 if (hdr->code != S3FWRN5_FW_RET_SUCCESS) { 155 ret = -EPROTO; 156 goto out; 157 } 158 159 kfree_skb(rsp); 160 161 /* Send signature data */ 162 163 ret = s3fwrn5_fw_prep_msg(fw_info, &msg, S3FWRN5_FW_MSG_DATA, 0, 164 sig_data, sig_size); 165 if (ret < 0) 166 return ret; 167 168 ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp); 169 kfree_skb(msg); 170 if (ret < 0) 171 return ret; 172 173 hdr = (struct s3fwrn5_fw_header *) rsp->data; 174 if (hdr->code != S3FWRN5_FW_RET_SUCCESS) 175 ret = -EPROTO; 176 177 out: 178 kfree_skb(rsp); 179 return ret; 180 } 181 182 static int s3fwrn5_fw_update_sector(struct s3fwrn5_fw_info *fw_info, 183 u32 base_addr, const void *data) 184 { 185 struct s3fwrn5_fw_cmd_update_sector args; 186 struct sk_buff *msg, *rsp = NULL; 187 struct s3fwrn5_fw_header *hdr; 188 int ret, i; 189 190 /* Send UPDATE_SECTOR command */ 191 192 args.base_address = base_addr; 193 194 ret = s3fwrn5_fw_prep_msg(fw_info, &msg, S3FWRN5_FW_MSG_CMD, 195 S3FWRN5_FW_CMD_UPDATE_SECTOR, &args, sizeof(args)); 196 if (ret < 0) 197 return ret; 198 199 ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp); 200 kfree_skb(msg); 201 if (ret < 0) 202 return ret; 203 204 hdr = (struct s3fwrn5_fw_header *) rsp->data; 205 if (hdr->code != S3FWRN5_FW_RET_SUCCESS) { 206 ret = -EPROTO; 207 goto err; 208 } 209 210 kfree_skb(rsp); 211 212 /* Send data split into 256-byte packets */ 213 214 for (i = 0; i < 16; ++i) { 215 ret = s3fwrn5_fw_prep_msg(fw_info, &msg, 216 S3FWRN5_FW_MSG_DATA, 0, data+256*i, 256); 217 if (ret < 0) 218 break; 219 220 ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp); 221 kfree_skb(msg); 222 if (ret < 0) 223 break; 224 225 hdr = (struct s3fwrn5_fw_header *) rsp->data; 226 if (hdr->code != S3FWRN5_FW_RET_SUCCESS) { 227 ret = -EPROTO; 228 goto err; 229 } 230 231 kfree_skb(rsp); 232 } 233 234 return ret; 235 236 err: 237 kfree_skb(rsp); 238 return ret; 239 } 240 241 static int s3fwrn5_fw_complete_update_mode(struct s3fwrn5_fw_info *fw_info) 242 { 243 struct sk_buff *msg, *rsp = NULL; 244 struct s3fwrn5_fw_header *hdr; 245 int ret; 246 247 /* Send COMPLETE_UPDATE_MODE command */ 248 249 ret = s3fwrn5_fw_prep_msg(fw_info, &msg, S3FWRN5_FW_MSG_CMD, 250 S3FWRN5_FW_CMD_COMPLETE_UPDATE_MODE, NULL, 0); 251 if (ret < 0) 252 return ret; 253 254 ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp); 255 kfree_skb(msg); 256 if (ret < 0) 257 return ret; 258 259 hdr = (struct s3fwrn5_fw_header *) rsp->data; 260 if (hdr->code != S3FWRN5_FW_RET_SUCCESS) 261 ret = -EPROTO; 262 263 kfree_skb(rsp); 264 265 return ret; 266 } 267 268 /* 269 * Firmware header stucture: 270 * 271 * 0x00 - 0x0B : Date and time string (w/o NUL termination) 272 * 0x10 - 0x13 : Firmware version 273 * 0x14 - 0x17 : Signature address 274 * 0x18 - 0x1B : Signature size 275 * 0x1C - 0x1F : Firmware image address 276 * 0x20 - 0x23 : Firmware sectors count 277 * 0x24 - 0x27 : Custom signature address 278 * 0x28 - 0x2B : Custom signature size 279 */ 280 281 #define S3FWRN5_FW_IMAGE_HEADER_SIZE 44 282 283 static int s3fwrn5_fw_request_firmware(struct s3fwrn5_fw_info *fw_info) 284 { 285 struct s3fwrn5_fw_image *fw = &fw_info->fw; 286 u32 sig_off; 287 u32 image_off; 288 u32 custom_sig_off; 289 int ret; 290 291 ret = request_firmware(&fw->fw, fw_info->fw_name, 292 &fw_info->ndev->nfc_dev->dev); 293 if (ret < 0) 294 return ret; 295 296 if (fw->fw->size < S3FWRN5_FW_IMAGE_HEADER_SIZE) 297 return -EINVAL; 298 299 memcpy(fw->date, fw->fw->data + 0x00, 12); 300 fw->date[12] = '\0'; 301 302 memcpy(&fw->version, fw->fw->data + 0x10, 4); 303 304 memcpy(&sig_off, fw->fw->data + 0x14, 4); 305 fw->sig = fw->fw->data + sig_off; 306 memcpy(&fw->sig_size, fw->fw->data + 0x18, 4); 307 308 memcpy(&image_off, fw->fw->data + 0x1C, 4); 309 fw->image = fw->fw->data + image_off; 310 memcpy(&fw->image_sectors, fw->fw->data + 0x20, 4); 311 312 memcpy(&custom_sig_off, fw->fw->data + 0x24, 4); 313 fw->custom_sig = fw->fw->data + custom_sig_off; 314 memcpy(&fw->custom_sig_size, fw->fw->data + 0x28, 4); 315 316 return 0; 317 } 318 319 static void s3fwrn5_fw_release_firmware(struct s3fwrn5_fw_info *fw_info) 320 { 321 release_firmware(fw_info->fw.fw); 322 } 323 324 static int s3fwrn5_fw_get_base_addr( 325 struct s3fwrn5_fw_cmd_get_bootinfo_rsp *bootinfo, u32 *base_addr) 326 { 327 int i; 328 static const struct { 329 u8 version[4]; 330 u32 base_addr; 331 } match[] = { 332 {{0x05, 0x00, 0x00, 0x00}, 0x00005000}, 333 {{0x05, 0x00, 0x00, 0x01}, 0x00003000}, 334 {{0x05, 0x00, 0x00, 0x02}, 0x00003000}, 335 {{0x05, 0x00, 0x00, 0x03}, 0x00003000}, 336 {{0x05, 0x00, 0x00, 0x05}, 0x00003000} 337 }; 338 339 for (i = 0; i < ARRAY_SIZE(match); ++i) 340 if (bootinfo->hw_version[0] == match[i].version[0] && 341 bootinfo->hw_version[1] == match[i].version[1] && 342 bootinfo->hw_version[3] == match[i].version[3]) { 343 *base_addr = match[i].base_addr; 344 return 0; 345 } 346 347 return -EINVAL; 348 } 349 350 static inline bool 351 s3fwrn5_fw_is_custom(struct s3fwrn5_fw_cmd_get_bootinfo_rsp *bootinfo) 352 { 353 return !!bootinfo->hw_version[2]; 354 } 355 356 int s3fwrn5_fw_setup(struct s3fwrn5_fw_info *fw_info) 357 { 358 struct s3fwrn5_fw_cmd_get_bootinfo_rsp bootinfo; 359 int ret; 360 361 /* Get firmware data */ 362 363 ret = s3fwrn5_fw_request_firmware(fw_info); 364 if (ret < 0) { 365 dev_err(&fw_info->ndev->nfc_dev->dev, 366 "Failed to get fw file, ret=%02x\n", ret); 367 return ret; 368 } 369 370 /* Get bootloader info */ 371 372 ret = s3fwrn5_fw_get_bootinfo(fw_info, &bootinfo); 373 if (ret < 0) { 374 dev_err(&fw_info->ndev->nfc_dev->dev, 375 "Failed to get bootinfo, ret=%02x\n", ret); 376 goto err; 377 } 378 379 /* Match hardware version to obtain firmware base address */ 380 381 ret = s3fwrn5_fw_get_base_addr(&bootinfo, &fw_info->base_addr); 382 if (ret < 0) { 383 dev_err(&fw_info->ndev->nfc_dev->dev, 384 "Unknown hardware version\n"); 385 goto err; 386 } 387 388 fw_info->sector_size = bootinfo.sector_size; 389 390 fw_info->sig_size = s3fwrn5_fw_is_custom(&bootinfo) ? 391 fw_info->fw.custom_sig_size : fw_info->fw.sig_size; 392 fw_info->sig = s3fwrn5_fw_is_custom(&bootinfo) ? 393 fw_info->fw.custom_sig : fw_info->fw.sig; 394 395 return 0; 396 397 err: 398 s3fwrn5_fw_release_firmware(fw_info); 399 return ret; 400 } 401 402 bool s3fwrn5_fw_check_version(struct s3fwrn5_fw_info *fw_info, u32 version) 403 { 404 struct s3fwrn5_fw_version *new = (void *) &fw_info->fw.version; 405 struct s3fwrn5_fw_version *old = (void *) &version; 406 407 if (new->major > old->major) 408 return true; 409 if (new->build1 > old->build1) 410 return true; 411 if (new->build2 > old->build2) 412 return true; 413 414 return false; 415 } 416 417 int s3fwrn5_fw_download(struct s3fwrn5_fw_info *fw_info) 418 { 419 struct s3fwrn5_fw_image *fw = &fw_info->fw; 420 u8 hash_data[SHA1_DIGEST_SIZE]; 421 struct crypto_shash *tfm; 422 u32 image_size, off; 423 int ret; 424 425 image_size = fw_info->sector_size * fw->image_sectors; 426 427 /* Compute SHA of firmware data */ 428 429 tfm = crypto_alloc_shash("sha1", 0, 0); 430 if (IS_ERR(tfm)) { 431 ret = PTR_ERR(tfm); 432 dev_err(&fw_info->ndev->nfc_dev->dev, 433 "Cannot allocate shash (code=%d)\n", ret); 434 goto out; 435 } 436 437 { 438 SHASH_DESC_ON_STACK(desc, tfm); 439 440 desc->tfm = tfm; 441 442 ret = crypto_shash_digest(desc, fw->image, image_size, 443 hash_data); 444 shash_desc_zero(desc); 445 } 446 447 crypto_free_shash(tfm); 448 if (ret) { 449 dev_err(&fw_info->ndev->nfc_dev->dev, 450 "Cannot compute hash (code=%d)\n", ret); 451 goto out; 452 } 453 454 /* Firmware update process */ 455 456 dev_info(&fw_info->ndev->nfc_dev->dev, 457 "Firmware update: %s\n", fw_info->fw_name); 458 459 ret = s3fwrn5_fw_enter_update_mode(fw_info, hash_data, 460 SHA1_DIGEST_SIZE, fw_info->sig, fw_info->sig_size); 461 if (ret < 0) { 462 dev_err(&fw_info->ndev->nfc_dev->dev, 463 "Unable to enter update mode\n"); 464 goto out; 465 } 466 467 for (off = 0; off < image_size; off += fw_info->sector_size) { 468 ret = s3fwrn5_fw_update_sector(fw_info, 469 fw_info->base_addr + off, fw->image + off); 470 if (ret < 0) { 471 dev_err(&fw_info->ndev->nfc_dev->dev, 472 "Firmware update error (code=%d)\n", ret); 473 goto out; 474 } 475 } 476 477 ret = s3fwrn5_fw_complete_update_mode(fw_info); 478 if (ret < 0) { 479 dev_err(&fw_info->ndev->nfc_dev->dev, 480 "Unable to complete update mode\n"); 481 goto out; 482 } 483 484 dev_info(&fw_info->ndev->nfc_dev->dev, 485 "Firmware update: success\n"); 486 487 out: 488 return ret; 489 } 490 491 void s3fwrn5_fw_init(struct s3fwrn5_fw_info *fw_info, const char *fw_name) 492 { 493 fw_info->parity = 0x00; 494 fw_info->rsp = NULL; 495 fw_info->fw.fw = NULL; 496 strcpy(fw_info->fw_name, fw_name); 497 init_completion(&fw_info->completion); 498 } 499 500 void s3fwrn5_fw_cleanup(struct s3fwrn5_fw_info *fw_info) 501 { 502 s3fwrn5_fw_release_firmware(fw_info); 503 } 504 505 int s3fwrn5_fw_recv_frame(struct nci_dev *ndev, struct sk_buff *skb) 506 { 507 struct s3fwrn5_info *info = nci_get_drvdata(ndev); 508 struct s3fwrn5_fw_info *fw_info = &info->fw_info; 509 510 BUG_ON(fw_info->rsp); 511 512 fw_info->rsp = skb; 513 514 complete(&fw_info->completion); 515 516 return 0; 517 } 518