wifi: rtw89: efuse: read firmware secure info v0 from efuse for WiFi 6 chips
authorPing-Ke Shih <pkshih@realtek.com>
Wed, 30 Oct 2024 02:21:30 +0000 (10:21 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Wed, 6 Nov 2024 05:57:17 +0000 (13:57 +0800)
WiFi 6 chips could program secure information in v0 or v1 format. Use
existing v1 parser or newly added v0 parser to recognize firmware key
that is going to be used.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20241030022135.11688-4-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/efuse.c

index 5fa59cd138c17e1d1bc697f4097c0b3fe0d35c73..ccee011c9975b554899480f061c7bfaa8d2edf95 100644 (file)
@@ -4516,11 +4516,14 @@ enum rtw89_fw_mss_dev_type {
 };
 
 struct rtw89_fw_secure {
-       bool secure_boot;
+       bool secure_boot: 1;
+       bool can_mss_v1: 1;
+       bool can_mss_v0: 1;
        u32 sb_sel_mgn;
        u8 mss_dev_type;
        u8 mss_cust_idx;
        u8 mss_key_num;
+       u8 mss_idx; /* v0 */
 };
 
 struct rtw89_fw_info {
index a02b04eecd056259de29cffe175aced6bed41baf..6c6c763510af6b78c9ebe9462470ec717cc36f6e 100644 (file)
 #define EFUSE_B2_MSSKEYNUM_MASK GENMASK(3, 0)
 #define EFUSE_B2_MSSCUSTIDX1_MASK BIT(6)
 
+#define EFUSE_EXTERNALPN_ADDR_AX 0x5EC
+#define EFUSE_CUSTOMER_ADDR_AX 0x5ED
+#define EFUSE_SERIALNUM_ADDR_AX 0x5ED
+
+#define EFUSE_B1_EXTERNALPN_MASK GENMASK(7, 0)
+#define EFUSE_B2_CUSTOMER_MASK GENMASK(3, 0)
+#define EFUSE_B2_SERIALNUM_MASK GENMASK(6, 4)
+
+#define OTP_KEY_INFO_NUM 2
+
+static const u8 otp_key_info_externalPN[OTP_KEY_INFO_NUM] = {0x0, 0x0};
+static const u8 otp_key_info_customer[OTP_KEY_INFO_NUM]   = {0x0, 0x1};
+static const u8 otp_key_info_serialNum[OTP_KEY_INFO_NUM]  = {0x0, 0x1};
+
 enum rtw89_efuse_bank {
        RTW89_EFUSE_BANK_WIFI,
        RTW89_EFUSE_BANK_BT,
@@ -397,24 +411,96 @@ static u8 get_mss_dev_type_idx(struct rtw89_dev *rtwdev, u8 mss_dev_type)
 
 int rtw89_efuse_recognize_mss_info_v1(struct rtw89_dev *rtwdev, u8 b1, u8 b2)
 {
+       const struct rtw89_chip_info *chip = rtwdev->chip;
        struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
        u8 mss_dev_type;
 
+       if (chip->chip_id == RTL8852B && b1 == 0xFF && b2 == 0x6E) {
+               mss_dev_type = MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_NON_COB;
+               sec->mss_cust_idx = 0;
+               sec->mss_key_num = 0;
+
+               goto mss_dev_type;
+       }
+
        mss_dev_type = u8_get_bits(b1, EFUSE_B1_MSSDEVTYPE_MASK);
        sec->mss_cust_idx = 0x1F - (u8_get_bits(b1, EFUSE_B1_MSSCUSTIDX0_MASK) |
                                    u8_get_bits(b2, EFUSE_B2_MSSCUSTIDX1_MASK) << 4);
        sec->mss_key_num = 0xF - u8_get_bits(b2, EFUSE_B2_MSSKEYNUM_MASK);
 
+mss_dev_type:
        sec->mss_dev_type = get_mss_dev_type_idx(rtwdev, mss_dev_type);
        if (sec->mss_dev_type == RTW89_FW_MSS_DEV_TYPE_FWSEC_INV) {
                rtw89_warn(rtwdev, "invalid mss_dev_type %d\n", mss_dev_type);
                return -ENOENT;
        }
 
+       sec->can_mss_v1 = true;
+
        return 0;
 }
 
+static
+int rtw89_efuse_recognize_mss_index_v0(struct rtw89_dev *rtwdev, u8 b1, u8 b2)
+{
+       struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
+       u8 externalPN;
+       u8 serialNum;
+       u8 customer;
+       u8 i;
+
+       externalPN = 0xFF - u8_get_bits(b1, EFUSE_B1_EXTERNALPN_MASK);
+       customer = 0xF - u8_get_bits(b2, EFUSE_B2_CUSTOMER_MASK);
+       serialNum = 0x7 - u8_get_bits(b2, EFUSE_B2_SERIALNUM_MASK);
+
+       for (i = 0; i < OTP_KEY_INFO_NUM; i++) {
+               if (externalPN == otp_key_info_externalPN[i] &&
+                   customer == otp_key_info_customer[i] &&
+                   serialNum == otp_key_info_serialNum[i]) {
+                       sec->mss_idx = i;
+                       sec->can_mss_v0 = true;
+                       return 0;
+               }
+       }
+
+       return -ENOENT;
+}
+
 int rtw89_efuse_read_fw_secure_ax(struct rtw89_dev *rtwdev)
 {
+       struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
+       u32 sec_addr = EFUSE_EXTERNALPN_ADDR_AX;
+       u32 sec_size = 2;
+       u8 sec_map[2];
+       u8 b1, b2;
+       int ret;
+
+       ret = rtw89_dump_physical_efuse_map(rtwdev, sec_map,
+                                           sec_addr, sec_size, false);
+       if (ret) {
+               rtw89_warn(rtwdev, "failed to dump secsel map\n");
+               return ret;
+       }
+
+       b1 = sec_map[0];
+       b2 = sec_map[1];
+
+       if (b1 == 0xFF && b2 == 0xFF)
+               return 0;
+
+       rtw89_efuse_recognize_mss_index_v0(rtwdev, b1, b2);
+       rtw89_efuse_recognize_mss_info_v1(rtwdev, b1, b2);
+       if (!sec->can_mss_v1 && !sec->can_mss_v0)
+               goto out;
+
+       sec->secure_boot = true;
+
+out:
+       rtw89_debug(rtwdev, RTW89_DBG_FW,
+                   "MSS secure_boot=%d(%d/%d) dev_type=%d cust_idx=%d key_num=%d mss_index=%d\n",
+                   sec->secure_boot, sec->can_mss_v0, sec->can_mss_v1,
+                   sec->mss_dev_type, sec->mss_cust_idx,
+                   sec->mss_key_num, sec->mss_idx);
+
        return 0;
 }