r8169_firmware.c (4926B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* r8169_firmware.c: RealTek 8169/8168/8101 ethernet driver. 3 * 4 * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw> 5 * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com> 6 * Copyright (c) a lot of people too. Please respect their work. 7 * 8 * See MAINTAINERS file for support contact information. 9 */ 10 11#include <linux/delay.h> 12#include <linux/firmware.h> 13 14#include "r8169_firmware.h" 15 16enum rtl_fw_opcode { 17 PHY_READ = 0x0, 18 PHY_DATA_OR = 0x1, 19 PHY_DATA_AND = 0x2, 20 PHY_BJMPN = 0x3, 21 PHY_MDIO_CHG = 0x4, 22 PHY_CLEAR_READCOUNT = 0x7, 23 PHY_WRITE = 0x8, 24 PHY_READCOUNT_EQ_SKIP = 0x9, 25 PHY_COMP_EQ_SKIPN = 0xa, 26 PHY_COMP_NEQ_SKIPN = 0xb, 27 PHY_WRITE_PREVIOUS = 0xc, 28 PHY_SKIPN = 0xd, 29 PHY_DELAY_MS = 0xe, 30}; 31 32struct fw_info { 33 u32 magic; 34 char version[RTL_VER_SIZE]; 35 __le32 fw_start; 36 __le32 fw_len; 37 u8 chksum; 38} __packed; 39 40#define FW_OPCODE_SIZE sizeof_field(struct rtl_fw_phy_action, code[0]) 41 42static bool rtl_fw_format_ok(struct rtl_fw *rtl_fw) 43{ 44 const struct firmware *fw = rtl_fw->fw; 45 struct fw_info *fw_info = (struct fw_info *)fw->data; 46 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; 47 48 if (fw->size < FW_OPCODE_SIZE) 49 return false; 50 51 if (!fw_info->magic) { 52 size_t i, size, start; 53 u8 checksum = 0; 54 55 if (fw->size < sizeof(*fw_info)) 56 return false; 57 58 for (i = 0; i < fw->size; i++) 59 checksum += fw->data[i]; 60 if (checksum != 0) 61 return false; 62 63 start = le32_to_cpu(fw_info->fw_start); 64 if (start > fw->size) 65 return false; 66 67 size = le32_to_cpu(fw_info->fw_len); 68 if (size > (fw->size - start) / FW_OPCODE_SIZE) 69 return false; 70 71 strscpy(rtl_fw->version, fw_info->version, RTL_VER_SIZE); 72 73 pa->code = (__le32 *)(fw->data + start); 74 pa->size = size; 75 } else { 76 if (fw->size % FW_OPCODE_SIZE) 77 return false; 78 79 strscpy(rtl_fw->version, rtl_fw->fw_name, RTL_VER_SIZE); 80 81 pa->code = (__le32 *)fw->data; 82 pa->size = fw->size / FW_OPCODE_SIZE; 83 } 84 85 return true; 86} 87 88static bool rtl_fw_data_ok(struct rtl_fw *rtl_fw) 89{ 90 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; 91 size_t index; 92 93 for (index = 0; index < pa->size; index++) { 94 u32 action = le32_to_cpu(pa->code[index]); 95 u32 val = action & 0x0000ffff; 96 u32 regno = (action & 0x0fff0000) >> 16; 97 98 switch (action >> 28) { 99 case PHY_READ: 100 case PHY_DATA_OR: 101 case PHY_DATA_AND: 102 case PHY_CLEAR_READCOUNT: 103 case PHY_WRITE: 104 case PHY_WRITE_PREVIOUS: 105 case PHY_DELAY_MS: 106 break; 107 108 case PHY_MDIO_CHG: 109 if (val > 1) 110 goto out; 111 break; 112 113 case PHY_BJMPN: 114 if (regno > index) 115 goto out; 116 break; 117 case PHY_READCOUNT_EQ_SKIP: 118 if (index + 2 >= pa->size) 119 goto out; 120 break; 121 case PHY_COMP_EQ_SKIPN: 122 case PHY_COMP_NEQ_SKIPN: 123 case PHY_SKIPN: 124 if (index + 1 + regno >= pa->size) 125 goto out; 126 break; 127 128 default: 129 dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action); 130 return false; 131 } 132 } 133 134 return true; 135out: 136 dev_err(rtl_fw->dev, "Out of range of firmware\n"); 137 return false; 138} 139 140void rtl_fw_write_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) 141{ 142 struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; 143 rtl_fw_write_t fw_write = rtl_fw->phy_write; 144 rtl_fw_read_t fw_read = rtl_fw->phy_read; 145 int predata = 0, count = 0; 146 size_t index; 147 148 for (index = 0; index < pa->size; index++) { 149 u32 action = le32_to_cpu(pa->code[index]); 150 u32 data = action & 0x0000ffff; 151 u32 regno = (action & 0x0fff0000) >> 16; 152 enum rtl_fw_opcode opcode = action >> 28; 153 154 if (!action) 155 break; 156 157 switch (opcode) { 158 case PHY_READ: 159 predata = fw_read(tp, regno); 160 count++; 161 break; 162 case PHY_DATA_OR: 163 predata |= data; 164 break; 165 case PHY_DATA_AND: 166 predata &= data; 167 break; 168 case PHY_BJMPN: 169 index -= (regno + 1); 170 break; 171 case PHY_MDIO_CHG: 172 if (data) { 173 fw_write = rtl_fw->mac_mcu_write; 174 fw_read = rtl_fw->mac_mcu_read; 175 } else { 176 fw_write = rtl_fw->phy_write; 177 fw_read = rtl_fw->phy_read; 178 } 179 180 break; 181 case PHY_CLEAR_READCOUNT: 182 count = 0; 183 break; 184 case PHY_WRITE: 185 fw_write(tp, regno, data); 186 break; 187 case PHY_READCOUNT_EQ_SKIP: 188 if (count == data) 189 index++; 190 break; 191 case PHY_COMP_EQ_SKIPN: 192 if (predata == data) 193 index += regno; 194 break; 195 case PHY_COMP_NEQ_SKIPN: 196 if (predata != data) 197 index += regno; 198 break; 199 case PHY_WRITE_PREVIOUS: 200 fw_write(tp, regno, predata); 201 break; 202 case PHY_SKIPN: 203 index += regno; 204 break; 205 case PHY_DELAY_MS: 206 msleep(data); 207 break; 208 } 209 } 210} 211 212void rtl_fw_release_firmware(struct rtl_fw *rtl_fw) 213{ 214 release_firmware(rtl_fw->fw); 215} 216 217int rtl_fw_request_firmware(struct rtl_fw *rtl_fw) 218{ 219 int rc; 220 221 rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev); 222 if (rc < 0) 223 goto out; 224 225 if (!rtl_fw_format_ok(rtl_fw) || !rtl_fw_data_ok(rtl_fw)) { 226 release_firmware(rtl_fw->fw); 227 rc = -EINVAL; 228 goto out; 229 } 230 231 return 0; 232out: 233 dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n", 234 rtl_fw->fw_name, rc); 235 return rc; 236}