diff mbox series

[7/8] wifi: rtw89: fw: use common function to parse security section for WiFi 6 chips

Message ID 20241030022135.11688-8-pkshih@realtek.com (mailing list archive)
State Accepted
Delegated to: Ping-Ke Shih
Headers show
Series wifi: rtw89: support firmware secure boot for WiFi 6 chips | expand

Commit Message

Ping-Ke Shih Oct. 30, 2024, 2:21 a.m. UTC
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>
---
 drivers/net/wireless/realtek/rtw89/fw.c | 57 +++++++++++++++++++------
 drivers/net/wireless/realtek/rtw89/fw.h |  1 +
 2 files changed, 46 insertions(+), 12 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 4229065e07e8..538622c29e42 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -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;
 	}
 
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index bd7680264849..efa63d444821 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -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 {