diff mbox series

[3/4] wifi: rtw89: fw: parse secure section from firmware file

Message ID 20240203003251.10641-4-pkshih@realtek.com (mailing list archive)
State Changes Requested
Delegated to: Kalle Valo
Headers show
Series wifi: rtw89: fw: support firmware secure boot | expand

Commit Message

Ping-Ke Shih Feb. 3, 2024, 12:32 a.m. UTC
A firmware file can contains more than one section with secure type, so
use secure information from efuse to choose the one with matched
cryptography method. Then choose key data from MSS poll (multiple security
section pool; see below picture) according to key_index from efuse.

Note that the size of MSS pool isn't included in section size defined
in firmware header, so we also need to parse header of MSS pool to get
its size as shift to parse next section.

If secure boot isn't supported by current hardware, the first secure
section will be adopted, and no need additional process to key data.

  +---------------------------+
  |      firmware header      |
  |                           |
  | +-----------------------+ |
  | | section type/size * N-|-|-------+
  | | ...                   | |       |
  | +-----------------------+ |       |
  +---------------------------+       |
  :                           :       |
  +---------------------------+ -\    |
  | secure section type (ID:9)|  |    |
  |                           |  | <--+
  |                           |  |
  +---------------------------+ -/
  |MSS Pool for above section |
  |                           |
  |                           |
  +---------------------------+

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/fw.c | 202 ++++++++++++++++++++++--
 drivers/net/wireless/realtek/rtw89/fw.h |  39 +++++
 2 files changed, 227 insertions(+), 14 deletions(-)

Comments

kernel test robot Feb. 3, 2024, 7:22 p.m. UTC | #1
Hi Ping-Ke,

kernel test robot noticed the following build warnings:

[auto build test WARNING on wireless-next/main]
[also build test WARNING on wireless/main linus/master v6.8-rc2 next-20240202]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Ping-Ke-Shih/wifi-rtw89-fw-consider-checksum-length-of-security-data/20240203-085038
base:   https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next.git main
patch link:    https://lore.kernel.org/r/20240203003251.10641-4-pkshih%40realtek.com
patch subject: [PATCH 3/4] wifi: rtw89: fw: parse secure section from firmware file
config: parisc-allmodconfig (https://download.01.org/0day-ci/archive/20240204/202402040350.rRpOepoU-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240204/202402040350.rRpOepoU-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202402040350.rRpOepoU-lkp@intel.com/

All warnings (new ones prefixed by >>):

   drivers/net/wireless/realtek/rtw89/fw.c: In function 'rtw89_fw_hdr_parser_v1':
>> drivers/net/wireless/realtek/rtw89/fw.c:384:88: warning: format '%lx' expects argument of type 'long unsigned int', but argument 9 has type 'int' [-Wformat=]
     384 |                             "section[%d] type=%d len=0x%-6x mssc=%d mssc_len=%d addr=%lx\n",
         |                                                                                      ~~^
         |                                                                                        |
         |                                                                                        long unsigned int
         |                                                                                      %x
     385 |                             i, section_info->type, section_info->len,
     386 |                             section_info->mssc, mssc_len, bin - fw);
         |                                                           ~~~~~~~~                      
         |                                                               |
         |                                                               int
   drivers/net/wireless/realtek/rtw89/fw.c:388:68: warning: format '%lx' expects argument of type 'long unsigned int', but argument 6 has type 'int' [-Wformat=]
     388 |                             "           ignore=%d key_addr=%p (0x%lx) key_len=%d key_idx=%d\n",
         |                                                                  ~~^
         |                                                                    |
         |                                                                    long unsigned int
         |                                                                  %x
     389 |                             section_info->ignore, section_info->key_addr,
     390 |                             section_info->key_addr ?
         |                             ~~~~~~~~~~~~~~~~~~~~~~~~                
     391 |                             section_info->key_addr - section_info->addr : 0,
         |                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         |                                                                         |
         |                                                                         int


vim +384 drivers/net/wireless/realtek/rtw89/fw.c

   322	
   323	static int rtw89_fw_hdr_parser_v1(struct rtw89_dev *rtwdev, const u8 *fw, u32 len,
   324					  struct rtw89_fw_bin_info *info)
   325	{
   326		const struct rtw89_fw_hdr_v1 *fw_hdr = (const struct rtw89_fw_hdr_v1 *)fw;
   327		struct rtw89_fw_hdr_section_info *section_info;
   328		const struct rtw89_fw_dynhdr_hdr *fwdynhdr;
   329		const struct rtw89_fw_hdr_section_v1 *section;
   330		const u8 *fw_end = fw + len;
   331		const u8 *bin;
   332		u32 base_hdr_len;
   333		u32 mssc_len;
   334		int ret;
   335		u32 i;
   336	
   337		info->section_num = le32_get_bits(fw_hdr->w6, FW_HDR_V1_W6_SEC_NUM);
   338		info->dsp_checksum = le32_get_bits(fw_hdr->w6, FW_HDR_V1_W6_DSP_CHKSUM);
   339		base_hdr_len = struct_size(fw_hdr, sections, info->section_num);
   340		info->dynamic_hdr_en = le32_get_bits(fw_hdr->w7, FW_HDR_V1_W7_DYN_HDR);
   341	
   342		if (info->dynamic_hdr_en) {
   343			info->hdr_len = le32_get_bits(fw_hdr->w5, FW_HDR_V1_W5_HDR_SIZE);
   344			info->dynamic_hdr_len = info->hdr_len - base_hdr_len;
   345			fwdynhdr = (const struct rtw89_fw_dynhdr_hdr *)(fw + base_hdr_len);
   346			if (le32_to_cpu(fwdynhdr->hdr_len) != info->dynamic_hdr_len) {
   347				rtw89_err(rtwdev, "[ERR]invalid fw dynamic header len\n");
   348				return -EINVAL;
   349			}
   350		} else {
   351			info->hdr_len = base_hdr_len;
   352			info->dynamic_hdr_len = 0;
   353		}
   354	
   355		bin = fw + info->hdr_len;
   356	
   357		/* jump to section header */
   358		section_info = info->section_info;
   359		for (i = 0; i < info->section_num; i++) {
   360			section = &fw_hdr->sections[i];
   361	
   362			section_info->type =
   363				le32_get_bits(section->w1, FWSECTION_HDR_V1_W1_SECTIONTYPE);
   364			section_info->len =
   365				le32_get_bits(section->w1, FWSECTION_HDR_V1_W1_SEC_SIZE);
   366			if (le32_get_bits(section->w1, FWSECTION_HDR_V1_W1_CHECKSUM))
   367				section_info->len += FWDL_SECTION_CHKSUM_LEN;
   368			section_info->redl = le32_get_bits(section->w1, FWSECTION_HDR_V1_W1_REDL);
   369			section_info->dladdr =
   370				le32_get_bits(section->w0, FWSECTION_HDR_V1_W0_DL_ADDR);
   371			section_info->addr = bin;
   372	
   373			if (section_info->type == FWDL_SECURITY_SECTION_TYPE) {
   374				ret = __parse_security_section(rtwdev, info, section_info,
   375							       section, bin, &mssc_len);
   376				if (ret)
   377					return ret;
   378			} else {
   379				section_info->mssc = 0;
   380				mssc_len = 0;
   381			}
   382	
   383			rtw89_debug(rtwdev, RTW89_DBG_FW,
 > 384				    "section[%d] type=%d len=0x%-6x mssc=%d mssc_len=%d addr=%lx\n",
   385				    i, section_info->type, section_info->len,
   386				    section_info->mssc, mssc_len, bin - fw);
   387			rtw89_debug(rtwdev, RTW89_DBG_FW,
   388				    "           ignore=%d key_addr=%p (0x%lx) key_len=%d key_idx=%d\n",
   389				    section_info->ignore, section_info->key_addr,
   390				    section_info->key_addr ?
   391				    section_info->key_addr - section_info->addr : 0,
   392				    section_info->key_len, section_info->key_idx);
   393	
   394			bin += section_info->len + mssc_len;
   395			section_info++;
   396		}
   397	
   398		if (fw_end != bin) {
   399			rtw89_err(rtwdev, "[ERR]fw bin size\n");
   400			return -EINVAL;
   401		}
   402	
   403		if (!info->secure_section_exist)
   404			rtw89_warn(rtwdev, "no firmware secure section\n");
   405	
   406		return 0;
   407	}
   408
Ping-Ke Shih Feb. 4, 2024, 1:31 a.m. UTC | #2
On Sun, 2024-02-04 at 03:22 +0800, kernel test robot wrote:
> 
>    drivers/net/wireless/realtek/rtw89/fw.c: In function 'rtw89_fw_hdr_parser_v1':
> > > drivers/net/wireless/realtek/rtw89/fw.c:384:88: warning: format '%lx' expects argument of type
> > > 'long unsigned int', but argument 9 has type 'int' [-Wformat=]
>      384 |                             "section[%d] type=%d len=0x%-6x mssc=%d mssc_len=%d
> addr=%lx\n",
>          |                                                                                      ~~
> ^
>          |                                                                                        
> |
>          |                                                                                        
> long unsigned int
>          |                                                                                      %x
>      385 |                             i, section_info->type, section_info->len,
>      386 |                             section_info->mssc, mssc_len, bin - fw);
>          |                                                           ~~~~~~~~
>          |                                                               |
>          |                                                               int

I looked for how to print out differences (subtraction) of points, and
"%tx" is the desired format [1]. I corrected this by v2.

[1] https://docs.kernel.org/core-api/printk-formats.html#pointer-differences

Ping-Ke
Kalle Valo Feb. 5, 2024, 6:47 a.m. UTC | #3
Ping-Ke Shih <pkshih@realtek.com> writes:

> On Sun, 2024-02-04 at 03:22 +0800, kernel test robot wrote:
>> 
>>    drivers/net/wireless/realtek/rtw89/fw.c: In function 'rtw89_fw_hdr_parser_v1':
>> > > drivers/net/wireless/realtek/rtw89/fw.c:384:88: warning: format
>> > > '%lx' expects argument of type
>> > > 'long unsigned int', but argument 9 has type 'int' [-Wformat=]
>>      384 | "section[%d] type=%d len=0x%-6x mssc=%d mssc_len=%d
>> addr=%lx\n",
>>          |                                                                                      ~~
>> ^
>>          |
>> |
>>          |
>> long unsigned int
>>          |                                                                                      %x
>>      385 |                             i, section_info->type, section_info->len,
>>      386 |                             section_info->mssc, mssc_len, bin - fw);
>>          |                                                           ~~~~~~~~
>>          |                                                               |
>>          |                                                               int
>
> I looked for how to print out differences (subtraction) of points, and
> "%tx" is the desired format [1]. I corrected this by v2.
>
> [1] https://docs.kernel.org/core-api/printk-formats.html#pointer-differences

Heh, never heard of %td and %tx before. Thanks for teaching us :)
diff mbox series

Patch

diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 00417364ab22..4f648071a5be 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -13,6 +13,8 @@ 
 #include "reg.h"
 #include "util.h"
 
+static const u8 mss_signature[] = {0x4D, 0x53, 0x53, 0x4B, 0x50, 0x4F, 0x4F, 0x4C};
+
 union rtw89_fw_element_arg {
 	size_t offset;
 	enum rtw89_rf_path rf_path;
@@ -163,6 +165,161 @@  static int rtw89_fw_hdr_parser_v0(struct rtw89_dev *rtwdev, const u8 *fw, u32 le
 	return 0;
 }
 
+static int __get_mssc_key_idx(struct rtw89_dev *rtwdev,
+			      const struct rtw89_fw_mss_pool_hdr *mss_hdr,
+			      u32 rmp_tbl_size, u32 *key_idx)
+{
+	struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
+	u32 sel_byte_idx;
+	u32 mss_sel_idx;
+	u8 sel_bit_idx;
+	int i;
+
+	if (sec->mss_dev_type == RTW89_FW_MSS_DEV_TYPE_FWSEC_DEF) {
+		if (!mss_hdr->defen)
+			return -ENOENT;
+
+		mss_sel_idx = sec->mss_cust_idx * le16_to_cpu(mss_hdr->msskey_num_max) +
+			      sec->mss_key_num;
+	} else {
+		if (mss_hdr->defen)
+			mss_sel_idx = FWDL_MSS_POOL_DEFKEYSETS_SIZE << 3;
+		else
+			mss_sel_idx = 0;
+		mss_sel_idx += sec->mss_dev_type * le16_to_cpu(mss_hdr->msskey_num_max) *
+						   le16_to_cpu(mss_hdr->msscust_max) +
+			       sec->mss_cust_idx * le16_to_cpu(mss_hdr->msskey_num_max) +
+			       sec->mss_key_num;
+	}
+
+	sel_byte_idx = mss_sel_idx >> 3;
+	sel_bit_idx = mss_sel_idx & 0x7;
+
+	if (sel_byte_idx >= rmp_tbl_size)
+		return -EFAULT;
+
+	if (!(mss_hdr->rmp_tbl[sel_byte_idx] & BIT(sel_bit_idx)))
+		return -ENOENT;
+
+	*key_idx = hweight8(mss_hdr->rmp_tbl[sel_byte_idx] & (BIT(sel_bit_idx) - 1));
+
+	for (i = 0; i < sel_byte_idx; i++)
+		*key_idx += hweight8(mss_hdr->rmp_tbl[i]);
+
+	return 0;
+}
+
+static int __parse_formatted_mssc(struct rtw89_dev *rtwdev,
+				  struct rtw89_fw_bin_info *info,
+				  struct rtw89_fw_hdr_section_info *section_info,
+				  const struct rtw89_fw_hdr_section_v1 *section,
+				  const void *content,
+				  u32 *mssc_len)
+{
+	const struct rtw89_fw_mss_pool_hdr *mss_hdr = content + section_info->len;
+	const union rtw89_fw_section_mssc_content *section_content = content;
+	struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
+	u32 rmp_tbl_size;
+	u32 key_sign_len;
+	u32 real_key_idx;
+	u32 sb_sel_ver;
+	int ret;
+
+	if (memcmp(mss_signature, mss_hdr->signature, sizeof(mss_signature)) != 0) {
+		rtw89_err(rtwdev, "[ERR] wrong MSS signature\n");
+		return -ENOENT;
+	}
+
+	if (mss_hdr->rmpfmt == MSS_POOL_RMP_TBL_BITMASK) {
+		rmp_tbl_size = (le16_to_cpu(mss_hdr->msskey_num_max) *
+				le16_to_cpu(mss_hdr->msscust_max) *
+				mss_hdr->mssdev_max) >> 3;
+		if (mss_hdr->defen)
+			rmp_tbl_size += FWDL_MSS_POOL_DEFKEYSETS_SIZE;
+	} else {
+		rtw89_err(rtwdev, "[ERR] MSS Key Pool Remap Table Format Unsupport:%X\n",
+			  mss_hdr->rmpfmt);
+		return -EINVAL;
+	}
+
+	if (rmp_tbl_size + sizeof(*mss_hdr) != le32_to_cpu(mss_hdr->key_raw_offset)) {
+		rtw89_err(rtwdev, "[ERR] MSS Key Pool Format Error:0x%X + 0x%X != 0x%X\n",
+			  rmp_tbl_size, (int)sizeof(*mss_hdr),
+			  le32_to_cpu(mss_hdr->key_raw_offset));
+		return -EINVAL;
+	}
+
+	key_sign_len = le16_to_cpu(section_content->key_sign_len.v) >> 2;
+	if (!key_sign_len)
+		key_sign_len = 512;
+
+	if (info->dsp_checksum)
+		key_sign_len += FWDL_SECURITY_CHKSUM_LEN;
+
+	*mssc_len = sizeof(*mss_hdr) + rmp_tbl_size +
+		    le16_to_cpu(mss_hdr->keypair_num) * key_sign_len;
+
+	if (!sec->secure_boot)
+		goto out;
+
+	sb_sel_ver = le32_to_cpu(section_content->sb_sel_ver.v);
+	if (sb_sel_ver && sb_sel_ver != sec->sb_sel_mgn)
+		goto ignore;
+
+	ret = __get_mssc_key_idx(rtwdev, mss_hdr, rmp_tbl_size, &real_key_idx);
+	if (ret)
+		goto ignore;
+
+	section_info->key_addr = content + section_info->len +
+				le32_to_cpu(mss_hdr->key_raw_offset) +
+				key_sign_len * real_key_idx;
+	section_info->key_len = key_sign_len;
+	section_info->key_idx = real_key_idx;
+
+out:
+	if (info->secure_section_exist) {
+		section_info->ignore = true;
+		return 0;
+	}
+
+	info->secure_section_exist = true;
+
+	return 0;
+
+ignore:
+	section_info->ignore = true;
+
+	return 0;
+}
+
+static int __parse_security_section(struct rtw89_dev *rtwdev,
+				    struct rtw89_fw_bin_info *info,
+				    struct rtw89_fw_hdr_section_info *section_info,
+				    const struct rtw89_fw_hdr_section_v1 *section,
+				    const void *content,
+				    u32 *mssc_len)
+{
+	int ret;
+
+	section_info->mssc =
+		le32_get_bits(section->w2, FWSECTION_HDR_V1_W2_MSSC);
+
+	if (section_info->mssc == FORMATTED_MSSC) {
+		ret = __parse_formatted_mssc(rtwdev, info, section_info,
+					     section, content, mssc_len);
+		if (ret)
+			return -EINVAL;
+	} else {
+		*mssc_len = section_info->mssc * FWDL_SECURITY_SIGLEN;
+		if (info->dsp_checksum)
+			*mssc_len += section_info->mssc * FWDL_SECURITY_CHKSUM_LEN;
+
+		info->secure_section_exist = true;
+	}
+
+	return 0;
+}
+
 static int rtw89_fw_hdr_parser_v1(struct rtw89_dev *rtwdev, const u8 *fw, u32 len,
 				  struct rtw89_fw_bin_info *info)
 {
@@ -173,7 +330,8 @@  static int rtw89_fw_hdr_parser_v1(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;
 
 	info->section_num = le32_get_bits(fw_hdr->w6, FW_HDR_V1_W6_SEC_NUM);
@@ -200,18 +358,9 @@  static int rtw89_fw_hdr_parser_v1(struct rtw89_dev *rtwdev, const u8 *fw, u32 le
 	section_info = info->section_info;
 	for (i = 0; i < info->section_num; i++) {
 		section = &fw_hdr->sections[i];
+
 		section_info->type =
 			le32_get_bits(section->w1, FWSECTION_HDR_V1_W1_SECTIONTYPE);
-		if (section_info->type == FWDL_SECURITY_SECTION_TYPE) {
-			section_info->mssc =
-				le32_get_bits(section->w2, FWSECTION_HDR_V1_W2_MSSC);
-			mssc_len += section_info->mssc * FWDL_SECURITY_SIGLEN;
-			if (info->dsp_checksum)
-				mssc_len += section_info->mssc * FWDL_SECURITY_CHKSUM_LEN;
-		} else {
-			section_info->mssc = 0;
-		}
-
 		section_info->len =
 			le32_get_bits(section->w1, FWSECTION_HDR_V1_W1_SEC_SIZE);
 		if (le32_get_bits(section->w1, FWSECTION_HDR_V1_W1_CHECKSUM))
@@ -220,15 +369,40 @@  static int rtw89_fw_hdr_parser_v1(struct rtw89_dev *rtwdev, const u8 *fw, u32 le
 		section_info->dladdr =
 			le32_get_bits(section->w0, FWSECTION_HDR_V1_W0_DL_ADDR);
 		section_info->addr = bin;
-		bin += section_info->len;
+
+		if (section_info->type == FWDL_SECURITY_SECTION_TYPE) {
+			ret = __parse_security_section(rtwdev, info, section_info,
+						       section, bin, &mssc_len);
+			if (ret)
+				return ret;
+		} else {
+			section_info->mssc = 0;
+			mssc_len = 0;
+		}
+
+		rtw89_debug(rtwdev, RTW89_DBG_FW,
+			    "section[%d] type=%d len=0x%-6x mssc=%d mssc_len=%d addr=%lx\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%lx) 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;
 	}
 
+	if (!info->secure_section_exist)
+		rtw89_warn(rtwdev, "no firmware secure section\n");
+
 	return 0;
 }
 
@@ -1106,7 +1280,7 @@  static int rtw89_fw_download_suit(struct rtw89_dev *rtwdev,
 				  struct rtw89_fw_suit *fw_suit)
 {
 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
-	struct rtw89_fw_bin_info info;
+	struct rtw89_fw_bin_info info = {};
 	int ret;
 
 	ret = rtw89_fw_hdr_parser(rtwdev, fw_suit, &info);
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index 5b536c2e365d..c05ddb0d5900 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -230,6 +230,10 @@  struct rtw89_fw_hdr_section_info {
 	u32 dladdr;
 	u32 mssc;
 	u8 type;
+	bool ignore;
+	const u8 *key_addr;
+	u32 key_len;
+	u32 key_idx;
 };
 
 struct rtw89_fw_bin_info {
@@ -238,6 +242,7 @@  struct rtw89_fw_bin_info {
 	bool dynamic_hdr_en;
 	u32 dynamic_hdr_len;
 	bool dsp_checksum;
+	bool secure_section_exist;
 	struct rtw89_fw_hdr_section_info section_info[FWDL_SECTION_MAX_NUM];
 };
 
@@ -538,6 +543,7 @@  struct rtw89_fw_hdr_section_v1 {
 #define FWSECTION_HDR_V1_W1_CHECKSUM BIT(28)
 #define FWSECTION_HDR_V1_W1_REDL BIT(29)
 #define FWSECTION_HDR_V1_W2_MSSC GENMASK(7, 0)
+#define FORMATTED_MSSC 0xFF
 #define FWSECTION_HDR_V1_W2_BBMCU_IDX GENMASK(27, 24)
 
 struct rtw89_fw_hdr_v1 {
@@ -578,6 +584,39 @@  static inline void SET_FW_HDR_PART_SIZE(void *fwhdr, u32 val)
 	le32p_replace_bits((__le32 *)fwhdr + 7, val, GENMASK(15, 0));
 }
 
+enum rtw89_fw_mss_pool_rmp_tbl_type {
+	MSS_POOL_RMP_TBL_BITMASK = 0x0,
+	MSS_POOL_RMP_TBL_RECORD = 0x1,
+};
+
+#define FWDL_MSS_POOL_DEFKEYSETS_SIZE 8
+
+struct rtw89_fw_mss_pool_hdr {
+	u8 signature[8]; /* equal to mss_signature[] */
+	__le32 rmp_tbl_offset;
+	__le32 key_raw_offset;
+	u8 defen;
+	u8 rsvd[3];
+	u8 rmpfmt; /* enum rtw89_fw_mss_pool_rmp_tbl_type */
+	u8 mssdev_max;
+	__le16 keypair_num;
+	__le16 msscust_max;
+	__le16 msskey_num_max;
+	__le32 rsvd3;
+	u8 rmp_tbl[];
+} __packed;
+
+union rtw89_fw_section_mssc_content {
+	struct {
+		u8 pad[58];
+		__le32 v;
+	} __packed sb_sel_ver;
+	struct {
+		u8 pad[60];
+		__le16 v;
+	} __packed key_sign_len;
+} __packed;
+
 static inline void SET_CTRL_INFO_MACID(void *table, u32 val)
 {
 	le32p_replace_bits((__le32 *)(table) + 0, val, GENMASK(6, 0));