summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomson Kang <thomson.kang@broadcom.com>2020-12-29 23:22:49 -0800
committerAhmed ElArabawy <arabawy@google.com>2021-01-08 00:25:20 +0000
commitfd0d2a4c83dc98e0e95d5813b324f30b2d09844f (patch)
treec3745ac911d6a04c2dff51d89277cb5afc83fd11
parente7cbe1ec9b2788b6f685843c27d8796c7eb21dc2 (diff)
downloadwlan-fd0d2a4c83dc98e0e95d5813b324f30b2d09844f.tar.gz
HAL: Support OTA update
[Simple operation] 1. Read config file both factory path and OTA path through Google Library. 2. If OTA path's version is higher than factory path and passed integrity, then download NVRA/CLM to driver before interface up. 3. Driver turn on with the OTA NVRAM/CLM files. Bug: 155333904 Test: Verified on Hikey Platform Change-Id: Ic7af972aeb36e8d0a1c33b983aeb174b1e853137
-rwxr-xr-xbcmdhd/wifi_hal/Android.mk3
-rwxr-xr-xbcmdhd/wifi_hal/common.h8
-rwxr-xr-xbcmdhd/wifi_hal/wifi_hal.cpp23
-rwxr-xr-xbcmdhd/wifi_hal/wifi_logger.cpp241
4 files changed, 275 insertions, 0 deletions
diff --git a/bcmdhd/wifi_hal/Android.mk b/bcmdhd/wifi_hal/Android.mk
index c326b65..d64dac5 100755
--- a/bcmdhd/wifi_hal/Android.mk
+++ b/bcmdhd/wifi_hal/Android.mk
@@ -41,6 +41,9 @@ LOCAL_C_INCLUDES += \
LOCAL_HEADER_LIBRARIES := libutils_headers liblog_headers
+LOCAL_SHARED_LIBRARIES += \
+ google_wifi_firmware_config_version_c_wrapper
+
LOCAL_SRC_FILES := \
wifi_hal.cpp \
rtt.cpp \
diff --git a/bcmdhd/wifi_hal/common.h b/bcmdhd/wifi_hal/common.h
index 8783e4d..c7f86a2 100755
--- a/bcmdhd/wifi_hal/common.h
+++ b/bcmdhd/wifi_hal/common.h
@@ -127,6 +127,10 @@ typedef enum {
ANDROID_NL80211_SUBCMD_VIOP_MODE_START = 0x2130,
ANDROID_NL80211_SUBCMD_VIOP_MODE_END = 0x213F,
+ /* define all OTA Download related commands between 0x2120 and 0x212F */
+ ANDROID_NL80211_SUBCMD_OTA_DOWNLOAD_START = 0x2120,
+ ANDROID_NL80211_SUBCMD_OTA_DOWNLOAD_END = 0x212F,
+
/* This is reserved for future usage */
} ANDROID_VENDOR_SUB_COMMAND;
@@ -211,6 +215,9 @@ typedef enum {
TWT_SUBCMD_CLR_STATS,
WIFI_SUBCMD_CONFIG_VOIP_MODE = ANDROID_NL80211_SUBCMD_VIOP_MODE_START,
+
+ WIFI_SUBCMD_GET_OTA_CURRUNT_INFO = ANDROID_NL80211_SUBCMD_OTA_DOWNLOAD_START,
+ WIFI_SUBCMD_OTA_UPDATE,
} WIFI_SUB_COMMAND;
typedef enum {
@@ -424,6 +431,7 @@ wifi_error wifi_start_hal(wifi_interface_handle iface);
wifi_error wifi_stop_hal(wifi_interface_handle iface);
wifi_interface_handle wifi_get_wlan_interface(wifi_handle info,
wifi_interface_handle *ifaceHandles, int numIfaceHandles);
+wifi_error wifi_hal_ota_update(wifi_interface_handle iface, uint32_t ota_version);
wifi_error wifi_hal_preInit(wifi_interface_handle iface);
/* API to get wake reason statistics */
wifi_error wifi_get_wake_reason_stats(wifi_interface_handle handle,
diff --git a/bcmdhd/wifi_hal/wifi_hal.cpp b/bcmdhd/wifi_hal/wifi_hal.cpp
index 0b93461..341c164 100755
--- a/bcmdhd/wifi_hal/wifi_hal.cpp
+++ b/bcmdhd/wifi_hal/wifi_hal.cpp
@@ -316,6 +316,28 @@ wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
return WIFI_SUCCESS;
}
+#include <google_wifi_firmware_config_version_info.h>
+
+static void
+wifi_check_valid_ota_version(wifi_interface_handle handle)
+{
+ bool valid = false;
+ int32_t default_ver = get_google_default_vendor_wifi_config_version();
+ int32_t ota_ver = get_google_ota_updated_wifi_config_version();
+ ALOGE("default_ver %d, ota_ver %d", default_ver, ota_ver);
+
+ if (ota_ver > default_ver) {
+ valid = verify_google_ota_updated_wifi_config_integrity();
+ }
+
+ if (valid) {
+ ALOGE("Valid config files of OTA.");
+ wifi_hal_ota_update(handle, ota_ver);
+ }
+ else {
+ ALOGE("Do not valid config files of OTA.");
+ }
+}
hal_info *halInfo = NULL;
wifi_error wifi_pre_initialize(void)
@@ -442,6 +464,7 @@ wifi_error wifi_pre_initialize(void)
if (wlan0Handle != NULL) {
ALOGE("Calling preInit");
if (!get_halutil_mode()) {
+ (void) wifi_check_valid_ota_version(wlan0Handle);
result = wifi_hal_preInit(wlan0Handle);
if (result != WIFI_SUCCESS) {
ALOGE("wifi_hal_preInit failed");
diff --git a/bcmdhd/wifi_hal/wifi_logger.cpp b/bcmdhd/wifi_hal/wifi_logger.cpp
index 7977381..68a797d 100755
--- a/bcmdhd/wifi_hal/wifi_logger.cpp
+++ b/bcmdhd/wifi_hal/wifi_logger.cpp
@@ -34,6 +34,7 @@
#include <netlink-private/object-api.h>
#include <netlink-private/types.h>
#include <unistd.h>
+#include <cutils/properties.h>
#include "nl80211_copy.h"
@@ -72,6 +73,20 @@ typedef enum {
LOGGER_SET_HAL_PID
} DEBUG_SUB_COMMAND;
+#define OTA_PATH "/data/vendor/firmware/wifi/"
+#define OTA_CLM_FILE "bcmdhd_clm.blob"
+#define OTA_NVRAM_FILE "bcmdhd.cal"
+#define HW_DEV_PROP "ro.revision"
+
+char ota_nvram_ext[10];
+typedef struct ota_info_buf {
+ u32 ota_clm_len;
+ const void *ota_clm_buf[1];
+ u32 ota_nvram_len;
+ const void *ota_nvram_buf[1];
+} ota_info_buf_t;
+u32 applied_ota_version = 0;
+
typedef enum {
LOGGER_ATTRIBUTE_INVALID = 0,
LOGGER_ATTRIBUTE_DRIVER_VER = 1,
@@ -152,8 +167,18 @@ typedef enum {
SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID = 0x0003
} SET_HAL_START_ATTRIBUTE;
+typedef enum {
+ OTA_DOWNLOAD_CLM_LENGTH_ATTR = 0x0001,
+ OTA_DOWNLOAD_CLM_ATTR = 0x0002,
+ OTA_DOWNLOAD_NVRAM_LENGTH_ATTR = 0x0003,
+ OTA_DOWNLOAD_NVRAM_ATTR = 0x0004,
+ OTA_SET_FORCE_REG_ON = 0x0005,
+ OTA_CUR_NVRAM_EXT_ATTR = 0x0006,
+} OTA_DOWNLOAD_ATTRIBUTE;
+
#define HAL_START_REQUEST_ID 2
#define HAL_RESTART_ID 3
+#define FILE_NAME_LEN 256
///////////////////////////////////////////////////////////////////////////////
class DebugCommand : public WifiCommand
{
@@ -1624,3 +1649,219 @@ wifi_error wifi_get_wake_reason_stats(wifi_interface_handle handle,
cmd->releaseRef();
return result;
}
+
+///////////////////////////////////////////////////////////////////////////////
+class OtaUpdateCommand : public WifiCommand
+{
+ int mErrCode;
+
+ public:
+ OtaUpdateCommand(wifi_interface_handle iface)
+ : WifiCommand("OtaUpdateCommand", iface, 0), mErrCode(0)
+ { }
+
+ int start() {
+ ALOGE("Start OtaUpdateCommand");
+ WifiRequest request(familyId(), ifaceId());
+
+ int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_GET_OTA_CURRUNT_INFO);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to set hal start; result = %d", result);
+ return result;
+ }
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to register set hal start response; result = %d", result);
+ }
+ return result;
+ }
+
+ int otaDownload(ota_info_buf_t* buf, uint32_t ota_version) {
+ u32 force_reg_on = false;
+ WifiRequest request(familyId(), ifaceId());
+ int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_OTA_UPDATE);
+
+ ALOGE("Download the OTA configuration");
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to set Hal preInit; result = %d", result);
+ return result;
+ }
+
+ nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+ result = request.put_u32(OTA_DOWNLOAD_CLM_LENGTH_ATTR, buf->ota_clm_len);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("otaDownload Failed to put data= %d", result);
+ return result;
+ }
+
+ result = request.put(OTA_DOWNLOAD_CLM_ATTR, buf->ota_clm_buf, sizeof(*buf->ota_clm_buf));
+ if (result != WIFI_SUCCESS) {
+ ALOGE("otaDownload Failed to put data= %d", result);
+ return result;
+ }
+
+ result = request.put_u32(OTA_DOWNLOAD_NVRAM_LENGTH_ATTR, buf->ota_nvram_len);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("otaDownload Failed to put data= %d", result);
+ return result;
+ }
+
+ result = request.put(OTA_DOWNLOAD_NVRAM_ATTR, buf->ota_clm_buf, sizeof(*buf->ota_clm_buf));
+ if (result != WIFI_SUCCESS) {
+ ALOGE("otaDownload Failed to put data= %d", result);
+ return result;
+ }
+
+ if (applied_ota_version != ota_version) {
+ force_reg_on = true;
+ applied_ota_version = ota_version;
+ }
+ result = request.put_u32(OTA_SET_FORCE_REG_ON, force_reg_on);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("otaDownload Failed to put data= %d", result);
+ return result;
+ }
+
+ request.attr_end(data);
+
+ result = requestResponse(request);
+ if (result != WIFI_SUCCESS) {
+ ALOGE("Failed to register set otaDownload; result = %d", result);
+ }
+
+ return result;
+ }
+
+ virtual int handleResponse(WifiEvent& reply) {
+ ALOGD("In OtaUpdateCommand::handleResponse");
+
+ if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+ ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+ return NL_SKIP;
+ }
+
+ int id = reply.get_vendor_id();
+ int subcmd = reply.get_vendor_subcmd();
+ nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+ int len = reply.get_vendor_data_len();
+
+ ALOGI("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
+
+ if (vendor_data == NULL || len == 0) {
+ ALOGE("no vendor data in GetPktFateCommand response; ignoring it\n");
+ return NL_SKIP;
+ }
+
+ for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+ switch (it.get_type()) {
+ case OTA_CUR_NVRAM_EXT_ATTR:
+ strncpy(ota_nvram_ext, (char*)it.get_string(), it.get_len());
+ ALOGE("Current Nvram ext [%s]\n", ota_nvram_ext);
+ break;
+ default:
+ ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
+ it.get_type(), it.get_len());
+ break;
+ }
+ }
+ return NL_OK;
+ }
+
+ virtual int handleEvent(WifiEvent& event) {
+ /* NO events! */
+ return NL_SKIP;
+ }
+};
+
+wifi_error read_ota_file(char* file, char** buffer, uint32_t* size)
+{
+ FILE* fp = NULL;
+ int file_size, count;
+ char* buf;
+ fp = fopen(file, "r");
+
+ if (fp == NULL) {
+ ALOGE("Read fail.");
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+
+ fseek(fp, 0, SEEK_END);
+ file_size = ftell(fp);
+
+ buf = (char *)malloc(file_size + 1);
+ if (buf == NULL) {
+ fclose(fp);
+ return WIFI_ERROR_UNKNOWN;
+ }
+ memset(buf, 0, file_size + 1);
+ fseek(fp, 0, SEEK_SET);
+ count = fread(buf, file_size, 1, fp);
+
+ *buffer = (char*) buf;
+ *size = file_size;
+ fclose(fp);
+ return WIFI_SUCCESS;
+}
+
+wifi_error wifi_hal_ota_update(wifi_interface_handle iface, uint32_t ota_version)
+{
+ wifi_handle handle = getWifiHandle(iface);
+ wifi_error result = WIFI_SUCCESS;
+ ota_info_buf_t buf;
+ char file_name[FILE_NAME_LEN];
+ char *buffer_nvram = NULL;
+ char *buffer_clm = NULL;
+ char prop_buf[PROPERTY_VALUE_MAX] = {0,};
+
+ OtaUpdateCommand *cmd = new OtaUpdateCommand(iface);
+ NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+ ALOGD("wifi_hal_ota_update, handle = %p, ota_version %d\n", handle, ota_version);
+
+ result = (wifi_error)cmd->start();
+ if (result != WIFI_SUCCESS) {
+ cmd->releaseRef();
+ return result;
+ }
+
+ sprintf(file_name, "%s%s", OTA_PATH, OTA_CLM_FILE);
+ ALOGE("[OTA] PATH CLM %s", file_name);
+ read_ota_file(file_name, &buffer_clm, &buf.ota_clm_len);
+ if (buffer_clm == NULL) {
+ ALOGE("buffer_clm is null");
+ goto exit;
+ }
+ buf.ota_clm_buf[0] = buffer_clm;
+
+ memset(file_name, 0, FILE_NAME_LEN);
+ property_get(HW_DEV_PROP, prop_buf, NULL);
+ sprintf(file_name, "%s%s_%s", OTA_PATH, OTA_NVRAM_FILE, prop_buf);
+ result = read_ota_file(file_name, &buffer_nvram, &buf.ota_nvram_len);
+ if (result != WIFI_SUCCESS) {
+ memset(file_name, 0, FILE_NAME_LEN);
+ sprintf(file_name, "%s%s", OTA_PATH, OTA_NVRAM_FILE);
+ read_ota_file(file_name, &buffer_nvram, &buf.ota_nvram_len);
+ }
+ if (buffer_nvram == NULL) {
+ ALOGE("buffer_nvram is null");
+ goto exit;
+ }
+
+ ALOGE("[OTA] PATH NVRAM %s", file_name);
+ buf.ota_nvram_buf[0] = buffer_nvram;
+ cmd->otaDownload(&buf, ota_version);
+
+exit:
+ if (buffer_clm != NULL) {
+ free(buffer_clm);
+ }
+ if (buffer_nvram != NULL) {
+ free(buffer_nvram);
+ }
+
+ cmd->releaseRef();
+
+ return result;
+}