blob: a524315657a76244e1ea04f6ba6d32e67241621f [file] [log] [blame]
/*
*
* Copyright (c) 2020 Project CHIP Authors
* Copyright (c) 2019 Nest Labs, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* Utilities for accessing persisted device configuration on
* platforms based on the MediaTek SDK.
*/
/* this file behaves like a config.h, comes first */
#include <functional>
#include <platform/internal/CHIPDeviceLayerInternal.h>
#include <platform/PlatformManager.h>
#include <platform/mt793x/MT793XConfig.h>
#include <lib/core/CHIPEncoding.h>
#include <platform/internal/testing/ConfigUnitTest.h>
#include "FreeRTOS.h"
#include "nvdm.h"
namespace chip {
namespace DeviceLayer {
namespace Internal {
// Factory config keys
const MT793XConfig::Key MT793XConfig::kConfigKey_SerialNum = { .Namespace = kConfigNamespace_ChipFactory, .Name = "serial-num" };
const MT793XConfig::Key MT793XConfig::kConfigKey_UniqueId = { .Namespace = kConfigNamespace_ChipFactory, .Name = "unique-id" };
const MT793XConfig::Key MT793XConfig::kConfigKey_MfrDeviceId = { .Namespace = kConfigNamespace_ChipFactory, .Name = "device-id" };
const MT793XConfig::Key MT793XConfig::kConfigKey_MfrDeviceCert = { .Namespace = kConfigNamespace_ChipFactory,
.Name = "device-cert" };
const MT793XConfig::Key MT793XConfig::kConfigKey_MfrDevicePrivateKey = { .Namespace = kConfigNamespace_ChipFactory,
.Name = "device-key" };
const MT793XConfig::Key MT793XConfig::kConfigKey_ManufacturingDate = { .Namespace = kConfigNamespace_ChipFactory,
.Name = "mfg-date" };
const MT793XConfig::Key MT793XConfig::kConfigKey_SetupPinCode = { .Namespace = kConfigNamespace_ChipFactory, .Name = "pin-code" };
const MT793XConfig::Key MT793XConfig::kConfigKey_MfrDeviceICACerts = { .Namespace = kConfigNamespace_ChipFactory,
.Name = "device-ca-certs" };
const MT793XConfig::Key MT793XConfig::kConfigKey_SetupDiscriminator = { .Namespace = kConfigNamespace_ChipFactory,
.Name = "discriminator" };
const MT793XConfig::Key MT793XConfig::kConfigKey_Spake2pIterationCount = { .Namespace = kConfigNamespace_ChipFactory,
.Name = "iteration-count" };
const MT793XConfig::Key MT793XConfig::kConfigKey_Spake2pSalt = { .Namespace = kConfigNamespace_ChipFactory, .Name = "salt" };
const MT793XConfig::Key MT793XConfig::kConfigKey_Spake2pVerifier = { .Namespace = kConfigNamespace_ChipFactory,
.Name = "verifier" };
// CHIP Config Keys
const MT793XConfig::Key MT793XConfig::kConfigKey_FabricId = { .Namespace = kConfigNamespace_ChipConfig, .Name = "fabric-id" };
const MT793XConfig::Key MT793XConfig::kConfigKey_ServiceConfig = { .Namespace = kConfigNamespace_ChipConfig,
.Name = "service-config" };
const MT793XConfig::Key MT793XConfig::kConfigKey_PairedAccountId = { .Namespace = kConfigNamespace_ChipConfig,
.Name = "account-id" };
const MT793XConfig::Key MT793XConfig::kConfigKey_ServiceId = { .Namespace = kConfigNamespace_ChipConfig, .Name = "service-id" };
const MT793XConfig::Key MT793XConfig::kConfigKey_FabricSecret = { .Namespace = kConfigNamespace_ChipConfig,
.Name = "fabric-secret" };
const MT793XConfig::Key MT793XConfig::kConfigKey_LastUsedEpochKeyId = { .Namespace = kConfigNamespace_ChipConfig,
.Name = "last-ek-id" };
const MT793XConfig::Key MT793XConfig::kConfigKey_FailSafeArmed = { .Namespace = kConfigNamespace_ChipConfig,
.Name = "fail-safe-armed" };
const MT793XConfig::Key MT793XConfig::kConfigKey_GroupKey = { .Namespace = kConfigNamespace_ChipConfig, .Name = "group-key" };
const MT793XConfig::Key MT793XConfig::kConfigKey_HardwareVersion = { .Namespace = kConfigNamespace_ChipConfig,
.Name = "hardware-ver" };
const MT793XConfig::Key MT793XConfig::kConfigKey_RegulatoryLocation = { .Namespace = kConfigNamespace_ChipConfig,
.Name = "reg-location" };
const MT793XConfig::Key MT793XConfig::kConfigKey_CountryCode = { .Namespace = kConfigNamespace_ChipConfig, .Name = "country-code" };
const MT793XConfig::Key MT793XConfig::kConfigKey_Breadcrumb = { .Namespace = kConfigNamespace_ChipConfig, .Name = "breadcrumb" };
const MT793XConfig::Key MT793XConfig::kConfigKey_WiFiSSID = { .Namespace = kConfigNamespace_ChipConfig, .Name = "wifi-ssid" };
const MT793XConfig::Key MT793XConfig::kConfigKey_WiFiPSK = { .Namespace = kConfigNamespace_ChipConfig, .Name = "wifi-psk" };
const MT793XConfig::Key MT793XConfig::kConfigKey_WiFiSEC = { .Namespace = kConfigNamespace_ChipConfig, .Name = "wifi-sec" };
const MT793XConfig::Key MT793XConfig::kConfigKey_GroupKeyBase = { .Namespace = kConfigNamespace_ChipConfig,
.Name = "group-key-base" };
const MT793XConfig::Key MT793XConfig::kConfigKey_GroupKeyMax = { .Namespace = kConfigNamespace_ChipConfig,
.Name = "group-key-max" };
const MT793XConfig::Key MT793XConfig::kConfigKey_LockUser = { .Namespace = kConfigNamespace_ChipConfig, .Name = "lock-user" };
const MT793XConfig::Key MT793XConfig::kConfigKey_Credential = { .Namespace = kConfigNamespace_ChipConfig, .Name = "credential" };
const MT793XConfig::Key MT793XConfig::kConfigKey_LockUserName = { .Namespace = kConfigNamespace_ChipConfig,
.Name = "lock-user-name" };
const MT793XConfig::Key MT793XConfig::kConfigKey_CredentialData = { .Namespace = kConfigNamespace_ChipConfig,
.Name = "credential-data" };
const MT793XConfig::Key MT793XConfig::kConfigKey_UserCredentials = { .Namespace = kConfigNamespace_ChipConfig,
.Name = "user-credential" };
const MT793XConfig::Key MT793XConfig::kConfigKey_WeekDaySchedules = { .Namespace = kConfigNamespace_ChipConfig,
.Name = "weekday-sched" };
const MT793XConfig::Key MT793XConfig::kConfigKey_YearDaySchedules = { .Namespace = kConfigNamespace_ChipConfig,
.Name = "yearday-sched" };
const MT793XConfig::Key MT793XConfig::kConfigKey_HolidaySchedules = { .Namespace = kConfigNamespace_ChipConfig,
.Name = "holiday-sched" };
// CHIP Counter Keys
const MT793XConfig::Key MT793XConfig::kConfigKey_BootCount = { .Namespace = kConfigNamespace_ChipCounters, .Name = "boot-count" };
const MT793XConfig::Key MT793XConfig::kConfigKey_TotalOperationalHours = { .Namespace = kConfigNamespace_ChipCounters,
.Name = "total-hours" };
#define NVDM_SEM_TIMEOUT_MS 5
static SemaphoreHandle_t nvdm_sem;
static StaticSemaphore_t nvdm_sem_struct;
CHIP_ERROR MT793XConfig::Init()
{
CHIP_ERROR err;
nvdm_status_t nvdm_status;
nvdm_sem = xSemaphoreCreateBinaryStatic(&nvdm_sem_struct);
if (nvdm_sem == NULL)
{
return CHIP_ERROR_NO_MEMORY;
}
nvdm_status = nvdm_init();
err = MapNvdmStatus(nvdm_status);
SuccessOrExit(err);
exit:
OnExit();
return CHIP_NO_ERROR;
}
CHIP_ERROR MT793XConfig::ReadConfigValue(Key key, bool & val)
{
CHIP_ERROR err;
uint32_t intVal;
uint32_t len = sizeof(bool);
if (pdFALSE == xSemaphoreTake(nvdm_sem, pdMS_TO_TICKS(NVDM_SEM_TIMEOUT_MS)))
{
err = CHIP_ERROR_TIMEOUT;
SuccessOrExit(err);
}
// Get NVDM item
err = MapNvdmStatus(nvdm_read_data_item(key.Namespace, key.Name, (uint8_t *) &intVal, &len));
SuccessOrExit(err);
val = (intVal != 0);
exit:
OnExit();
return err;
}
CHIP_ERROR MT793XConfig::ReadConfigValue(Key key, uint32_t & val)
{
CHIP_ERROR err;
uint32_t len = sizeof(uint32_t);
if (pdFALSE == xSemaphoreTake(nvdm_sem, pdMS_TO_TICKS(NVDM_SEM_TIMEOUT_MS)))
{
err = CHIP_ERROR_TIMEOUT;
SuccessOrExit(err);
}
if (key.Namespace == MT793XConfig::kConfigKey_SetupDiscriminator.Namespace &&
key.Name == MT793XConfig::kConfigKey_SetupDiscriminator.Name)
{
uint8_t mac_addr[WIFI_MAC_ADDRESS_LENGTH] = { 0 };
auto mFilogicCtx = PlatformMgrImpl().mFilogicCtx;
filogic_wifi_mac_addr_get_sync(mFilogicCtx, FILOGIC_WIFI_OPMODE_STA, mac_addr);
val = (*(reinterpret_cast<uint32_t *>(mac_addr))) & 0xFFF;
err = CHIP_NO_ERROR;
}
else
{
// Get NVDM item
err = MapNvdmStatus(nvdm_read_data_item(key.Namespace, key.Name, (uint8_t *) &val, &len));
SuccessOrExit(err);
}
exit:
OnExit();
return err;
}
CHIP_ERROR MT793XConfig::ReadConfigValue(Key key, uint64_t & val)
{
CHIP_ERROR err;
uint32_t len = sizeof(uint64_t);
if (pdFALSE == xSemaphoreTake(nvdm_sem, pdMS_TO_TICKS(NVDM_SEM_TIMEOUT_MS)))
{
err = CHIP_ERROR_TIMEOUT;
SuccessOrExit(err);
}
// Get NVDM item
err = MapNvdmStatus(nvdm_read_data_item(key.Namespace, key.Name, (uint8_t *) &val, &len));
SuccessOrExit(err);
exit:
OnExit();
return err;
}
CHIP_ERROR MT793XConfig::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen)
{
CHIP_ERROR err;
outLen = bufSize;
if (pdFALSE == xSemaphoreTake(nvdm_sem, pdMS_TO_TICKS(NVDM_SEM_TIMEOUT_MS)))
{
err = CHIP_ERROR_TIMEOUT;
SuccessOrExit(err);
}
// Get NVDM item
err = MapNvdmStatus(nvdm_read_data_item(key.Namespace, key.Name, (uint8_t *) buf, (uint32_t *) &outLen));
SuccessOrExit(err);
exit:
OnExit();
return err;
}
CHIP_ERROR MT793XConfig::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen)
{
CHIP_ERROR err;
outLen = bufSize;
if (pdFALSE == xSemaphoreTake(nvdm_sem, pdMS_TO_TICKS(NVDM_SEM_TIMEOUT_MS)))
{
err = CHIP_ERROR_TIMEOUT;
SuccessOrExit(err);
}
// Get NVDM item
err = MapNvdmStatus(nvdm_read_data_item(key.Namespace, key.Name, (uint8_t *) buf, (uint32_t *) &outLen));
SuccessOrExit(err);
exit:
OnExit();
return err;
}
CHIP_ERROR MT793XConfig::ReadConfigValueCounter(uint8_t counterIdx, uint32_t & val)
{
val = 0;
return CHIP_NO_ERROR;
}
CHIP_ERROR MT793XConfig::WriteConfigValue(Key key, bool val)
{
CHIP_ERROR err;
uint32_t intVal = val ? 1 : 0;
uint32_t len = sizeof(bool);
if (pdFALSE == xSemaphoreTake(nvdm_sem, pdMS_TO_TICKS(NVDM_SEM_TIMEOUT_MS)))
{
err = CHIP_ERROR_TIMEOUT;
SuccessOrExit(err);
}
// Set NVDM item
err = MapNvdmStatus(nvdm_write_data_item(key.Namespace, key.Name, NVDM_DATA_ITEM_TYPE_RAW_DATA, (uint8_t *) &intVal, len));
SuccessOrExit(err);
exit:
OnExit();
return err;
}
CHIP_ERROR MT793XConfig::WriteConfigValue(Key key, uint32_t val)
{
CHIP_ERROR err;
uint32_t len = sizeof(uint32_t);
if (pdFALSE == xSemaphoreTake(nvdm_sem, pdMS_TO_TICKS(NVDM_SEM_TIMEOUT_MS)))
{
err = CHIP_ERROR_TIMEOUT;
SuccessOrExit(err);
}
// Set NVDM item
err = MapNvdmStatus(nvdm_write_data_item(key.Namespace, key.Name, NVDM_DATA_ITEM_TYPE_RAW_DATA, (uint8_t *) &val, len));
SuccessOrExit(err);
exit:
OnExit();
return err;
}
CHIP_ERROR MT793XConfig::WriteConfigValue(Key key, uint64_t val)
{
CHIP_ERROR err;
uint32_t len = sizeof(uint64_t);
if (pdFALSE == xSemaphoreTake(nvdm_sem, pdMS_TO_TICKS(NVDM_SEM_TIMEOUT_MS)))
{
err = CHIP_ERROR_TIMEOUT;
SuccessOrExit(err);
}
// Set NVDM item
err = MapNvdmStatus(nvdm_write_data_item(key.Namespace, key.Name, NVDM_DATA_ITEM_TYPE_RAW_DATA, (uint8_t *) &val, len));
SuccessOrExit(err);
exit:
OnExit();
return err;
}
CHIP_ERROR MT793XConfig::WriteConfigValueStr(Key key, const char * str)
{
return WriteConfigValueStr(key, str, (str != NULL) ? strlen(str) : 0);
}
CHIP_ERROR MT793XConfig::WriteConfigValueStr(Key key, const char * str, size_t strLen)
{
CHIP_ERROR err;
if (pdFALSE == xSemaphoreTake(nvdm_sem, pdMS_TO_TICKS(NVDM_SEM_TIMEOUT_MS)))
{
err = CHIP_ERROR_TIMEOUT;
SuccessOrExit(err);
}
// Set NVDM item
err = MapNvdmStatus(nvdm_write_data_item(key.Namespace, key.Name, NVDM_DATA_ITEM_TYPE_STRING, (uint8_t *) str, strLen));
SuccessOrExit(err);
exit:
OnExit();
return err;
}
CHIP_ERROR MT793XConfig::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen)
{
CHIP_ERROR err;
if (pdFALSE == xSemaphoreTake(nvdm_sem, pdMS_TO_TICKS(NVDM_SEM_TIMEOUT_MS)))
{
err = CHIP_ERROR_TIMEOUT;
SuccessOrExit(err);
}
// Set NVDM item
err = MapNvdmStatus(nvdm_write_data_item(key.Namespace, key.Name, NVDM_DATA_ITEM_TYPE_RAW_DATA, (uint8_t *) data, dataLen));
SuccessOrExit(err);
exit:
OnExit();
return err;
}
CHIP_ERROR MT793XConfig::WriteConfigValueCounter(uint8_t counterIdx, uint32_t val)
{
return CHIP_NO_ERROR;
}
CHIP_ERROR MT793XConfig::ClearConfigValue(Key key)
{
CHIP_ERROR err;
if (pdFALSE == xSemaphoreTake(nvdm_sem, pdMS_TO_TICKS(NVDM_SEM_TIMEOUT_MS)))
{
err = CHIP_ERROR_TIMEOUT;
SuccessOrExit(err);
}
// Delete NVDM item
err = MapNvdmStatus(nvdm_delete_data_item(key.Namespace, key.Name));
SuccessOrExit(err);
exit:
OnExit();
return err;
}
bool MT793XConfig::ConfigValueExists(Key key)
{
CHIP_ERROR err;
char group_name[32];
char data_item_name[32];
bool ret = false;
if (pdFALSE == xSemaphoreTake(nvdm_sem, pdMS_TO_TICKS(NVDM_SEM_TIMEOUT_MS)))
{
err = CHIP_ERROR_TIMEOUT;
SuccessOrExit(err);
}
// Query NVDM item
nvdm_query_begin();
while (nvdm_query_next_group_name(group_name) == NVDM_STATUS_OK)
{
if (!strcmp(group_name, key.Namespace))
{
while (nvdm_query_next_data_item_name(data_item_name) == NVDM_STATUS_OK)
{
if (!strcmp(data_item_name, key.Name))
{
ret = true;
}
}
}
}
nvdm_query_end();
exit:
OnExit();
return ret;
}
CHIP_ERROR MT793XConfig::FactoryResetConfig(void)
{
CHIP_ERROR err;
if (pdFALSE == xSemaphoreTake(nvdm_sem, pdMS_TO_TICKS(NVDM_SEM_TIMEOUT_MS)))
{
err = CHIP_ERROR_TIMEOUT;
SuccessOrExit(err);
}
// Deletes all 'Config' type objects
// Note- 'Factory' and 'Counter' type are NOT deleted.
err = MapNvdmStatus(nvdm_delete_group(kConfigNamespace_ChipConfig));
SuccessOrExit(err);
exit:
OnExit();
return err;
}
CHIP_ERROR MT793XConfig::MapNvdmStatus(nvdm_status_t nvdm_status)
{
CHIP_ERROR err;
// NVDM_STATUS_INVALID_PARAMETER = -5, /**< The user parameter is invalid. */
// NVDM_STATUS_ITEM_NOT_FOUND = -4, /**< The data item wasn't found by the NVDM. */
// NVDM_STATUS_INSUFFICIENT_SPACE = -3, /**< No space is available in the flash. */
// NVDM_STATUS_INCORRECT_CHECKSUM = -2, /**< The NVDM found a checksum error when reading the data item. */
// NVDM_STATUS_ERROR = -1, /**< An unknown error occurred. */
// NVDM_STATUS_OK = 0, /**< The operation was successful. */
switch (nvdm_status)
{
case NVDM_STATUS_OK:
err = CHIP_NO_ERROR;
break;
case NVDM_STATUS_ITEM_NOT_FOUND:
err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
break;
case NVDM_STATUS_INCORRECT_CHECKSUM:
err = CHIP_ERROR_INTEGRITY_CHECK_FAILED;
break;
case NVDM_STATUS_INSUFFICIENT_SPACE:
err = CHIP_ERROR_BUFFER_TOO_SMALL;
break;
case NVDM_STATUS_INVALID_PARAMETER:
err = CHIP_ERROR_INVALID_ARGUMENT;
break;
case NVDM_STATUS_ERROR:
err = CHIP_ERROR_INTERNAL;
break;
default:
err = CHIP_ERROR_INTERNAL;
break;
}
return err;
}
void MT793XConfig::RunConfigUnitTest()
{
// Run common unit test.
::chip::DeviceLayer::Internal::RunConfigUnitTest<MT793XConfig>();
}
void MT793XConfig::OnExit()
{
xSemaphoreGive(nvdm_sem);
}
} // namespace Internal
} // namespace DeviceLayer
} // namespace chip