diff options
author | Thomson Kang <thomson.kang@broadcom.com> | 2020-12-29 23:22:49 -0800 |
---|---|---|
committer | Ahmed ElArabawy <arabawy@google.com> | 2021-01-08 00:25:20 +0000 |
commit | fd0d2a4c83dc98e0e95d5813b324f30b2d09844f (patch) | |
tree | c3745ac911d6a04c2dff51d89277cb5afc83fd11 | |
parent | e7cbe1ec9b2788b6f685843c27d8796c7eb21dc2 (diff) | |
download | wlan-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-x | bcmdhd/wifi_hal/Android.mk | 3 | ||||
-rwxr-xr-x | bcmdhd/wifi_hal/common.h | 8 | ||||
-rwxr-xr-x | bcmdhd/wifi_hal/wifi_hal.cpp | 23 | ||||
-rwxr-xr-x | bcmdhd/wifi_hal/wifi_logger.cpp | 241 |
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; +} |