summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/vendorcode/google/chromeos/sar.c152
1 files changed, 64 insertions, 88 deletions
diff --git a/src/vendorcode/google/chromeos/sar.c b/src/vendorcode/google/chromeos/sar.c
index 8b31e8125e..83c1c0ca20 100644
--- a/src/vendorcode/google/chromeos/sar.c
+++ b/src/vendorcode/google/chromeos/sar.c
@@ -2,111 +2,87 @@
#include <cbfs.h>
#include <console/console.h>
+#include <drivers/vpd/vpd.h>
#include <lib.h>
-#include <types.h>
-#include <string.h>
#include <sar.h>
-#include <drivers/vpd/vpd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <types.h>
#define WIFI_SAR_CBFS_FILENAME "wifi_sar_defaults.hex"
-#define CROS_VPD_WIFI_SAR_NAME "wifi_sar"
-
-static int load_sar_file_from_cbfs(void *buf, size_t buffer_size)
-{
- const char *filename = get_wifi_sar_cbfs_filename();
- if (filename == NULL)
- filename = WIFI_SAR_CBFS_FILENAME;
- return cbfs_load(filename, buf, buffer_size);
-}
-
-/* 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
+/*
+ * Retrieve WiFi SAR limits data from CBFS and decode it
+ * WiFi SAR data is expected in the 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;
- /* 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 the buffer size. */
- char wifi_sar_limit_str[2 * sizeof(struct wifi_sar_limits) + 1];
- uint8_t bin_buffer[sizeof(struct wifi_sar_limits)];
- const size_t buffer_size = ARRAY_SIZE(wifi_sar_limit_str);
- 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 (!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);
+ const char *filename;
+ size_t sar_str_len, sar_bin_len;
+ char *sar_str;
+ int ret = -1;
+
+ /*
+ * If GEO_SAR_ENABLE is not selected, SAR file does not contain
+ * delta table settings.
+ */
+ if (CONFIG(GEO_SAR_ENABLE))
+ sar_bin_len = sizeof(struct wifi_sar_limits);
+ else
+ sar_bin_len = sizeof(struct wifi_sar_limits) -
+ sizeof(struct wifi_sar_delta_table);
+
+ /*
+ * Each hex digit is represented as a character in CBFS SAR file. Thus,
+ * the SAR file is double the size of its binary buffer equivalent.
+ * Hence, the buffer size allocated for SAR file is:
+ * `2 * sar_bin_len + 1`
+ * 1 additional byte is allocated to store the terminating '\0'.
+ */
+ sar_str_len = 2 * sar_bin_len + 1;
+ sar_str = malloc(sar_str_len);
+
+ if (!sar_str) {
+ printk(BIOS_ERR, "Failed to allocate space for SAR string!\n");
+ return ret;
}
- /* Try to read the SAR limit entry from VPD */
- if (!vpd_gets(wifi_sar_limit_key, wifi_sar_limit_str,
- buffer_size, VPD_RO_THEN_RW)) {
- printk(BIOS_DEBUG, "Could not locate '%s' in VPD.\n",
- wifi_sar_limit_key);
+ printk(BIOS_DEBUG, "Checking CBFS for default SAR values\n");
- if (!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);
+ filename = get_wifi_sar_cbfs_filename();
+ if (filename == NULL)
+ filename = WIFI_SAR_CBFS_FILENAME;
- 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;
- }
+ if (cbfs_load(filename, sar_str, sar_str_len) != sar_str_len) {
+ printk(BIOS_ERR, "%s has bad len in CBFS\n", filename);
+ goto done;
}
- /* Decode the heximal encoded string to binary values */
- if (hexstrtobin(wifi_sar_limit_str, bin_buffer, bin_buff_adjusted_size)
- < bin_buff_adjusted_size) {
+ memset(sar_limits, 0, sizeof(*sar_limits));
+ if (hexstrtobin(sar_str, (uint8_t *)sar_limits, sar_bin_len) != sar_bin_len) {
printk(BIOS_ERR, "Error: wifi_sar contains non-hex value!\n");
- return -1;
+ goto done;
}
- memset(sar_limits, 0, sizeof(*sar_limits));
- memcpy(sar_limits, bin_buffer, bin_buff_adjusted_size);
- return 0;
+ ret = 0;
+done:
+ free(sar_str);
+ return ret;
}
__weak