wifi: rtw89: efuse: read firmware secure info v0 from efuse for WiFi 6 chips

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
This commit is contained in:
Ping-Ke Shih 2024-10-30 10:21:30 +08:00
parent 0ce1df1cc3
commit e1551a79c4
2 changed files with 90 additions and 1 deletions

View 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 {

View File

@ -16,6 +16,20 @@
#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;
}