diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/vendorcode/google/chromeos/sar.c | 152 |
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 |