wifi: rtw89: fw: use common function to parse security section for WiFi 6 chips
authorPing-Ke Shih <pkshih@realtek.com>
Wed, 30 Oct 2024 02:21:34 +0000 (10:21 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Wed, 6 Nov 2024 06:00:44 +0000 (14:00 +0800)
The MSSC (multiple security section count) can be regular number (shown in
below figure) or 0xFF (supported already). For WiFi 7 or newer WiFi 6
chips, the MSSC will be 0xFF. But early WiFi 6 chip such as RTL8852B
could be either one of the cases.

Extend __parse_security_section() to support both with/without secure
boot mode accordingly.

           +---------------------------+ -\
           |      firmware header      |  |
           |                           |  |
           | +-----------------------+ |  |
           | | section type/size * N | |  |
           | +-----------------------+ |  |
           +---------------------------+ -/
           :                           :
           +---------------------------+ -\
           | secure section type (ID:9)|  |
           |                           |  |
      +----|-> [ security key data ]   |  |
      |    +---------------------------+ -/
      |    |MSS Pool for above section |
      |    |  [ security key data 1 ]  |
      +----|- [ security key data 2 ]  |
by mss_idx |  [ security key data 3 ]  |
           |  ...                 M    | * M = MSSC (MSSC != 0xFF)
           +---------------------------+

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

index 5849579a628ef3de5f5dbac4613b6706eb7f6df4..2191c037d72e40d11abbc620a81290bd8440d04c 100644 (file)
@@ -56,6 +56,11 @@ static void rtw89_fw_c2h_cmd_handle(struct rtw89_dev *rtwdev,
                                    struct sk_buff *skb);
 static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb,
                                 struct rtw89_wait_info *wait, unsigned int cond);
+static int __parse_security_section(struct rtw89_dev *rtwdev,
+                                   struct rtw89_fw_bin_info *info,
+                                   struct rtw89_fw_hdr_section_info *section_info,
+                                   const void *content,
+                                   u32 *mssc_len);
 
 static struct sk_buff *rtw89_fw_h2c_alloc_skb(struct rtw89_dev *rtwdev, u32 len,
                                              bool header)
@@ -132,7 +137,8 @@ static int rtw89_fw_hdr_parser_v0(struct rtw89_dev *rtwdev, const u8 *fw, u32 le
        const u8 *fw_end = fw + len;
        const u8 *bin;
        u32 base_hdr_len;
-       u32 mssc_len = 0;
+       u32 mssc_len;
+       int ret;
        u32 i;
 
        if (!info)
@@ -164,29 +170,47 @@ static int rtw89_fw_hdr_parser_v0(struct rtw89_dev *rtwdev, const u8 *fw, u32 le
                section = &fw_hdr->sections[i];
                section_info->type =
                        le32_get_bits(section->w1, FWSECTION_HDR_W1_SECTIONTYPE);
+               section_info->len = le32_get_bits(section->w1, FWSECTION_HDR_W1_SEC_SIZE);
+
+               if (le32_get_bits(section->w1, FWSECTION_HDR_W1_CHECKSUM))
+                       section_info->len += FWDL_SECTION_CHKSUM_LEN;
+               section_info->redl = le32_get_bits(section->w1, FWSECTION_HDR_W1_REDL);
+               section_info->dladdr =
+                       le32_get_bits(section->w0, FWSECTION_HDR_W0_DL_ADDR) & 0x1fffffff;
+               section_info->addr = bin;
+
                if (section_info->type == FWDL_SECURITY_SECTION_TYPE) {
                        section_info->mssc =
                                le32_get_bits(section->w2, FWSECTION_HDR_W2_MSSC);
-                       mssc_len += section_info->mssc * FWDL_SECURITY_SIGLEN;
+
+                       ret = __parse_security_section(rtwdev, info, section_info,
+                                                      bin, &mssc_len);
+                       if (ret)
+                               return ret;
 
                        if (sec->secure_boot && chip->chip_id == RTL8852B)
                                section_info->len_override = 960;
                } else {
                        section_info->mssc = 0;
+                       mssc_len = 0;
                }
 
-               section_info->len = le32_get_bits(section->w1, FWSECTION_HDR_W1_SEC_SIZE);
-               if (le32_get_bits(section->w1, FWSECTION_HDR_W1_CHECKSUM))
-                       section_info->len += FWDL_SECTION_CHKSUM_LEN;
-               section_info->redl = le32_get_bits(section->w1, FWSECTION_HDR_W1_REDL);
-               section_info->dladdr =
-                       le32_get_bits(section->w0, FWSECTION_HDR_W0_DL_ADDR) & 0x1fffffff;
-               section_info->addr = bin;
-               bin += section_info->len;
+               rtw89_debug(rtwdev, RTW89_DBG_FW,
+                           "section[%d] type=%d len=0x%-6x mssc=%d mssc_len=%d addr=%tx\n",
+                           i, section_info->type, section_info->len,
+                           section_info->mssc, mssc_len, bin - fw);
+               rtw89_debug(rtwdev, RTW89_DBG_FW,
+                           "           ignore=%d key_addr=%p (0x%tx) key_len=%d key_idx=%d\n",
+                           section_info->ignore, section_info->key_addr,
+                           section_info->key_addr ?
+                           section_info->key_addr - section_info->addr : 0,
+                           section_info->key_len, section_info->key_idx);
+
+               bin += section_info->len + mssc_len;
                section_info++;
        }
 
-       if (fw_end != bin + mssc_len) {
+       if (fw_end != bin) {
                rtw89_err(rtwdev, "[ERR]fw bin size\n");
                return -EINVAL;
        }
@@ -326,9 +350,10 @@ static int __parse_security_section(struct rtw89_dev *rtwdev,
                                    const void *content,
                                    u32 *mssc_len)
 {
+       struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
        int ret;
 
-       if (section_info->mssc == FORMATTED_MSSC) {
+       if ((section_info->mssc & FORMATTED_MSSC_MASK) == FORMATTED_MSSC) {
                ret = __parse_formatted_mssc(rtwdev, info, section_info,
                                             content, mssc_len);
                if (ret)
@@ -338,6 +363,14 @@ static int __parse_security_section(struct rtw89_dev *rtwdev,
                if (info->dsp_checksum)
                        *mssc_len += section_info->mssc * FWDL_SECURITY_CHKSUM_LEN;
 
+               if (sec->secure_boot) {
+                       if (sec->mss_idx >= section_info->mssc)
+                               return -EFAULT;
+                       section_info->key_addr = content + section_info->len +
+                                                sec->mss_idx * FWDL_SECURITY_SIGLEN;
+                       section_info->key_len = FWDL_SECURITY_SIGLEN;
+               }
+
                info->secure_section_exist = true;
        }
 
index bd768026484928d9fded7a2076e993a5516e2740..efa63d44482106cb54566b60fbaefd9dc91c9a12 100644 (file)
@@ -583,6 +583,7 @@ struct rtw89_fw_hdr_section_v1 {
 #define FWSECTION_HDR_V1_W1_REDL BIT(29)
 #define FWSECTION_HDR_V1_W2_MSSC GENMASK(7, 0)
 #define FORMATTED_MSSC 0xFF
+#define FORMATTED_MSSC_MASK GENMASK(7, 0)
 #define FWSECTION_HDR_V1_W2_BBMCU_IDX GENMASK(27, 24)
 
 struct rtw89_fw_hdr_v1 {