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