aboutsummaryrefslogtreecommitdiff
path: root/src/vendorcode/google/chromeos/sar.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/google/chromeos/sar.c')
-rw-r--r--src/vendorcode/google/chromeos/sar.c107
1 files changed, 83 insertions, 24 deletions
diff --git a/src/vendorcode/google/chromeos/sar.c b/src/vendorcode/google/chromeos/sar.c
index 954492b822..fc72dc1348 100644
--- a/src/vendorcode/google/chromeos/sar.c
+++ b/src/vendorcode/google/chromeos/sar.c
@@ -1,7 +1,7 @@
/*
* This file is part of the coreboot project.
*
- * Copyright (C) 2017 Intel Corp.
+ * Copyright (C) 2017-2018 Intel Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -12,6 +12,8 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+
+#include <cbfs.h>
#include <console/console.h>
#include <lib.h>
#include <types.h>
@@ -19,44 +21,101 @@
#include <sar.h>
#include "cros_vpd.h"
-/* Retrieve the wifi SAR limits data from VPD and decode it */
+#define WIFI_SAR_CBFS_FILENAME "wifi_sar_defaults.hex"
+
+static int load_sar_file_from_cbfs(void *buf, size_t buffer_size)
+{
+ return cbfs_boot_load_file(WIFI_SAR_CBFS_FILENAME, buf,
+ buffer_size, CBFS_TYPE_RAW);
+}
+
+/* Retrieve the wifi SAR limits data from VPD and decode it
+
+For VPD: key,value pair is in this format
+"wifi_sar"=[<WRDD><EWRD>][WGDS]
+
+WIFI SAR data in CBFS file is expected in same format: [<WRDD><EWRD>][WGDS]
+
+[<WRDD><EWRD>] = NUM_SAR_LIMITS * BYTES_PER_SAR_LIMIT bytes.
+[WGDS]=[WGDS_VERSION][WGDS_DATA]
+
+For [WGDS_VERSION] 0x00,
+[WGDS_DATA] = [GROUP#0][GROUP#1][GROUP#2]
+
+[GROUP#<i>] =
+ [2.4Ghz – Max Allowed][2.4Ghz – Chain A Offset]
+ [2.4Ghz – Chain B Offset][5Ghz – Max Allowed]
+ [5Ghz – Chain A Offset][5Ghz – Chain B Offset]
+
+[GROUP#0] is for FCC
+[GROUP#1] is for Europe/Japan
+[GROUP#2] is for ROW
+
+*/
int get_wifi_sar_limits(struct wifi_sar_limits *sar_limits)
{
const char *wifi_sar_limit_key = CROS_VPD_WIFI_SAR_NAME;
- /*
- * cros_vpd_gets() reads in one less than size characters from the VPD
+ /* cros_vpd_gets() reads in one less than size characters from the VPD
* with a terminating null byte ('\0') stored as the last character into
- * the buffer, thus the increasing by 1 for buffer_size.
- */
+ * the buffer, thus the increasing by 1 for buffer_size. */
const size_t buffer_size = (sizeof(struct wifi_sar_limits) /
- sizeof(uint8_t)) * 2 + 1;
+ sizeof(uint8_t)) * 2 + 1;
char wifi_sar_limit_str[buffer_size];
uint8_t bin_buffer[sizeof(struct wifi_sar_limits)];
- int i;
+ size_t sar_cbfs_len, sar_expected_len, bin_buff_adjusted_size;
+
+ /* keep it backward compatible. Some older platform are shipping
+ without GEO SAR and so older wifi_sar VPD key */
+
+ sar_expected_len = buffer_size;
+ bin_buff_adjusted_size = sizeof(struct wifi_sar_limits);
+
+ if (!IS_ENABLED(CONFIG_GEO_SAR_ENABLE)) {
+ sar_expected_len = buffer_size -
+ sizeof(struct wifi_sar_delta_table) *
+ sizeof(uint8_t) * 2;
+ bin_buff_adjusted_size = sizeof(struct wifi_sar_limits) -
+ sizeof(struct wifi_sar_delta_table);
+ }
/* Try to read the SAR limit entry from VPD */
if (!cros_vpd_gets(wifi_sar_limit_key, wifi_sar_limit_str,
- ARRAY_SIZE(wifi_sar_limit_str))) {
- printk(BIOS_ERR,
- "Error: Could not locate '%s' in VPD\n",
- wifi_sar_limit_key);
- return -1;
+ buffer_size)) {
+ printk(BIOS_ERR, "Error: Could not locate '%s' in VPD.\n",
+ wifi_sar_limit_key);
+
+ if (!IS_ENABLED(CONFIG_WIFI_SAR_CBFS))
+ return -1;
+
+ printk(BIOS_DEBUG, "Checking CBFS for default SAR values\n");
+
+ sar_cbfs_len = load_sar_file_from_cbfs(
+ (void *) wifi_sar_limit_str,
+ sar_expected_len);
+
+ if (sar_cbfs_len != sar_expected_len) {
+ printk(BIOS_ERR, "%s has bad len in CBFS\n",
+ WIFI_SAR_CBFS_FILENAME);
+ return -1;
+ }
+ } else {
+ /* VPD key "wifi_sar" found. strlen is checked with addition of
+ * 1 as we have created buffer size 1 char larger for the reason
+ * mentioned at start of this function itself */
+ if (strlen(wifi_sar_limit_str) + 1 != sar_expected_len) {
+ printk(BIOS_ERR, "WIFI SAR key has bad len in VPD\n");
+ return -1;
+ }
}
- printk(BIOS_DEBUG, "VPD wifi_sar = %s\n", wifi_sar_limit_str);
/* Decode the heximal encoded string to binary values */
- if (hexstrtobin(wifi_sar_limit_str, bin_buffer,
- sizeof(struct wifi_sar_limits))
- < sizeof(struct wifi_sar_limits)) {
- printk(BIOS_ERR,
- "Error: VPD wifi_sar contains non-heximal value!\n");
+ if (hexstrtobin(wifi_sar_limit_str, bin_buffer, bin_buff_adjusted_size)
+ < bin_buff_adjusted_size) {
+ printk(BIOS_ERR, "Error: wifi_sar contains non-hex value!\n");
return -1;
}
- /* Fill the sar_limits structure with the decoded data */
- for (i = 0; i < NUM_SAR_LIMITS; i++)
- memcpy(sar_limits->sar_limit[i],
- &bin_buffer[BYTES_PER_SAR_LIMIT * i],
- BYTES_PER_SAR_LIMIT);
+ memset(sar_limits, 0, sizeof(*sar_limits));
+ memcpy(sar_limits, bin_buffer, bin_buff_adjusted_size);
return 0;
}