17f32f0e2SVladimir Kondratyev /*- 27f32f0e2SVladimir Kondratyev * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 37f32f0e2SVladimir Kondratyev * 47f32f0e2SVladimir Kondratyev * Copyright (c) 2013 Adrian Chadd <adrian@freebsd.org> 57f32f0e2SVladimir Kondratyev * Copyright (c) 2019 Vladimir Kondratyev <wulf@FreeBSD.org> 67f32f0e2SVladimir Kondratyev * 77f32f0e2SVladimir Kondratyev * Redistribution and use in source and binary forms, with or without 87f32f0e2SVladimir Kondratyev * modification, are permitted provided that the following conditions 97f32f0e2SVladimir Kondratyev * are met: 107f32f0e2SVladimir Kondratyev * 1. Redistributions of source code must retain the above copyright 117f32f0e2SVladimir Kondratyev * notice, this list of conditions and the following disclaimer. 127f32f0e2SVladimir Kondratyev * 2. Redistributions in binary form must reproduce the above copyright 137f32f0e2SVladimir Kondratyev * notice, this list of conditions and the following disclaimer in the 147f32f0e2SVladimir Kondratyev * documentation and/or other materials provided with the distribution. 157f32f0e2SVladimir Kondratyev * 167f32f0e2SVladimir Kondratyev * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 177f32f0e2SVladimir Kondratyev * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 187f32f0e2SVladimir Kondratyev * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 197f32f0e2SVladimir Kondratyev * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 207f32f0e2SVladimir Kondratyev * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 217f32f0e2SVladimir Kondratyev * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 227f32f0e2SVladimir Kondratyev * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 237f32f0e2SVladimir Kondratyev * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 247f32f0e2SVladimir Kondratyev * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 257f32f0e2SVladimir Kondratyev * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 267f32f0e2SVladimir Kondratyev * SUCH DAMAGE. 277f32f0e2SVladimir Kondratyev * 287f32f0e2SVladimir Kondratyev * $FreeBSD$ 297f32f0e2SVladimir Kondratyev */ 307f32f0e2SVladimir Kondratyev 317f32f0e2SVladimir Kondratyev #include <sys/types.h> 327f32f0e2SVladimir Kondratyev #include <sys/endian.h> 337f32f0e2SVladimir Kondratyev #include <sys/stat.h> 347f32f0e2SVladimir Kondratyev 357f32f0e2SVladimir Kondratyev #include <err.h> 367f32f0e2SVladimir Kondratyev #include <errno.h> 377f32f0e2SVladimir Kondratyev #include <fcntl.h> 387f32f0e2SVladimir Kondratyev #include <stdio.h> 397f32f0e2SVladimir Kondratyev #include <stdlib.h> 407f32f0e2SVladimir Kondratyev #include <string.h> 417f32f0e2SVladimir Kondratyev #include <unistd.h> 427f32f0e2SVladimir Kondratyev 437f32f0e2SVladimir Kondratyev #include "iwmbt_fw.h" 447f32f0e2SVladimir Kondratyev #include "iwmbt_dbg.h" 457f32f0e2SVladimir Kondratyev 467f32f0e2SVladimir Kondratyev int 477f32f0e2SVladimir Kondratyev iwmbt_fw_read(struct iwmbt_firmware *fw, const char *fwname) 487f32f0e2SVladimir Kondratyev { 497f32f0e2SVladimir Kondratyev int fd; 507f32f0e2SVladimir Kondratyev struct stat sb; 517f32f0e2SVladimir Kondratyev unsigned char *buf; 527f32f0e2SVladimir Kondratyev ssize_t r; 537f32f0e2SVladimir Kondratyev int i; 547f32f0e2SVladimir Kondratyev 557f32f0e2SVladimir Kondratyev fd = open(fwname, O_RDONLY); 567f32f0e2SVladimir Kondratyev if (fd < 0) { 577f32f0e2SVladimir Kondratyev warn("%s: open: %s", __func__, fwname); 587f32f0e2SVladimir Kondratyev return (0); 597f32f0e2SVladimir Kondratyev } 607f32f0e2SVladimir Kondratyev 617f32f0e2SVladimir Kondratyev if (fstat(fd, &sb) != 0) { 627f32f0e2SVladimir Kondratyev warn("%s: stat: %s", __func__, fwname); 637f32f0e2SVladimir Kondratyev close(fd); 647f32f0e2SVladimir Kondratyev return (0); 657f32f0e2SVladimir Kondratyev } 667f32f0e2SVladimir Kondratyev 677f32f0e2SVladimir Kondratyev buf = calloc(1, sb.st_size); 687f32f0e2SVladimir Kondratyev if (buf == NULL) { 697f32f0e2SVladimir Kondratyev warn("%s: calloc", __func__); 707f32f0e2SVladimir Kondratyev close(fd); 717f32f0e2SVladimir Kondratyev return (0); 727f32f0e2SVladimir Kondratyev } 737f32f0e2SVladimir Kondratyev 747f32f0e2SVladimir Kondratyev i = 0; 757f32f0e2SVladimir Kondratyev /* XXX handle partial reads */ 767f32f0e2SVladimir Kondratyev r = read(fd, buf, sb.st_size); 777f32f0e2SVladimir Kondratyev if (r < 0) { 787f32f0e2SVladimir Kondratyev warn("%s: read", __func__); 797f32f0e2SVladimir Kondratyev free(buf); 807f32f0e2SVladimir Kondratyev close(fd); 817f32f0e2SVladimir Kondratyev return (0); 827f32f0e2SVladimir Kondratyev } 837f32f0e2SVladimir Kondratyev 847f32f0e2SVladimir Kondratyev if (r != sb.st_size) { 857f32f0e2SVladimir Kondratyev iwmbt_err("read len %d != file size %d", 867f32f0e2SVladimir Kondratyev (int) r, 877f32f0e2SVladimir Kondratyev (int) sb.st_size); 887f32f0e2SVladimir Kondratyev free(buf); 897f32f0e2SVladimir Kondratyev close(fd); 907f32f0e2SVladimir Kondratyev return (0); 917f32f0e2SVladimir Kondratyev } 927f32f0e2SVladimir Kondratyev 937f32f0e2SVladimir Kondratyev /* We have everything, so! */ 947f32f0e2SVladimir Kondratyev 957f32f0e2SVladimir Kondratyev memset(fw, 0, sizeof(*fw)); 967f32f0e2SVladimir Kondratyev 977f32f0e2SVladimir Kondratyev fw->fwname = strdup(fwname); 987f32f0e2SVladimir Kondratyev fw->len = sb.st_size; 997f32f0e2SVladimir Kondratyev fw->buf = buf; 1007f32f0e2SVladimir Kondratyev 1017f32f0e2SVladimir Kondratyev close(fd); 1027f32f0e2SVladimir Kondratyev return (1); 1037f32f0e2SVladimir Kondratyev } 1047f32f0e2SVladimir Kondratyev 1057f32f0e2SVladimir Kondratyev void 1067f32f0e2SVladimir Kondratyev iwmbt_fw_free(struct iwmbt_firmware *fw) 1077f32f0e2SVladimir Kondratyev { 1087f32f0e2SVladimir Kondratyev if (fw->fwname) 1097f32f0e2SVladimir Kondratyev free(fw->fwname); 1107f32f0e2SVladimir Kondratyev if (fw->buf) 1117f32f0e2SVladimir Kondratyev free(fw->buf); 1127f32f0e2SVladimir Kondratyev memset(fw, 0, sizeof(*fw)); 1137f32f0e2SVladimir Kondratyev } 1147f32f0e2SVladimir Kondratyev 1157f32f0e2SVladimir Kondratyev char * 1167f32f0e2SVladimir Kondratyev iwmbt_get_fwname(struct iwmbt_version *ver, struct iwmbt_boot_params *params, 1177f32f0e2SVladimir Kondratyev const char *prefix, const char *suffix) 1187f32f0e2SVladimir Kondratyev { 119*da93a73fSVladimir Kondratyev struct stat sb; 1207f32f0e2SVladimir Kondratyev char *fwname; 1217f32f0e2SVladimir Kondratyev 1227f32f0e2SVladimir Kondratyev switch (ver->hw_variant) { 123fe70d7b2SPhilippe Michaud-Boudreault case 0x07: /* 7260 */ 124*da93a73fSVladimir Kondratyev case 0x08: /* 7265 */ 125fe70d7b2SPhilippe Michaud-Boudreault asprintf(&fwname, "%s/ibt-hw-%x.%x.%x-fw-%x.%x.%x.%x.%x.%s", 126fe70d7b2SPhilippe Michaud-Boudreault prefix, 127fe70d7b2SPhilippe Michaud-Boudreault le16toh(ver->hw_platform), 128fe70d7b2SPhilippe Michaud-Boudreault le16toh(ver->hw_variant), 129fe70d7b2SPhilippe Michaud-Boudreault le16toh(ver->hw_revision), 130fe70d7b2SPhilippe Michaud-Boudreault le16toh(ver->fw_variant), 131fe70d7b2SPhilippe Michaud-Boudreault le16toh(ver->fw_revision), 132fe70d7b2SPhilippe Michaud-Boudreault le16toh(ver->fw_build_num), 133fe70d7b2SPhilippe Michaud-Boudreault le16toh(ver->fw_build_ww), 134fe70d7b2SPhilippe Michaud-Boudreault le16toh(ver->fw_build_yy), 135fe70d7b2SPhilippe Michaud-Boudreault suffix); 136*da93a73fSVladimir Kondratyev /* 137*da93a73fSVladimir Kondratyev * Fallback to the default firmware patch if 138*da93a73fSVladimir Kondratyev * the correct firmware patch file is not found. 139*da93a73fSVladimir Kondratyev */ 140*da93a73fSVladimir Kondratyev if (stat(fwname, &sb) != 0 && errno == ENOENT) { 141*da93a73fSVladimir Kondratyev free(fwname); 142*da93a73fSVladimir Kondratyev asprintf(&fwname, "%s/ibt-hw-%x.%x.%s", 143*da93a73fSVladimir Kondratyev prefix, 144*da93a73fSVladimir Kondratyev le16toh(ver->hw_platform), 145*da93a73fSVladimir Kondratyev le16toh(ver->hw_variant), 146*da93a73fSVladimir Kondratyev suffix); 147*da93a73fSVladimir Kondratyev } 148fe70d7b2SPhilippe Michaud-Boudreault break; 149fe70d7b2SPhilippe Michaud-Boudreault 1507f32f0e2SVladimir Kondratyev case 0x0b: /* 8260 */ 1517f32f0e2SVladimir Kondratyev case 0x0c: /* 8265 */ 1527f32f0e2SVladimir Kondratyev asprintf(&fwname, "%s/ibt-%u-%u.%s", 1537f32f0e2SVladimir Kondratyev prefix, 1547f32f0e2SVladimir Kondratyev le16toh(ver->hw_variant), 1557f32f0e2SVladimir Kondratyev le16toh(params->dev_revid), 1567f32f0e2SVladimir Kondratyev suffix); 1577f32f0e2SVladimir Kondratyev break; 1587f32f0e2SVladimir Kondratyev 1597f32f0e2SVladimir Kondratyev case 0x11: /* 9560 */ 1607f32f0e2SVladimir Kondratyev case 0x12: /* 9260 */ 1617f32f0e2SVladimir Kondratyev case 0x13: 1627f32f0e2SVladimir Kondratyev case 0x14: /* 22161 */ 1637f32f0e2SVladimir Kondratyev asprintf(&fwname, "%s/ibt-%u-%u-%u.%s", 1647f32f0e2SVladimir Kondratyev prefix, 1657f32f0e2SVladimir Kondratyev le16toh(ver->hw_variant), 1667f32f0e2SVladimir Kondratyev le16toh(ver->hw_revision), 1677f32f0e2SVladimir Kondratyev le16toh(ver->fw_revision), 1687f32f0e2SVladimir Kondratyev suffix); 1697f32f0e2SVladimir Kondratyev break; 1707f32f0e2SVladimir Kondratyev 1717f32f0e2SVladimir Kondratyev default: 1727f32f0e2SVladimir Kondratyev fwname = NULL; 1737f32f0e2SVladimir Kondratyev } 1747f32f0e2SVladimir Kondratyev 1757f32f0e2SVladimir Kondratyev return (fwname); 1767f32f0e2SVladimir Kondratyev } 177