#include "hal-api-compatibility-checker-parser.h"
#include "hal-api-compatibility-checker-util.h"
-#define HAL_COMMON_DEFAULT_HAL_INFO_INI "/hal/etc/hal-info.ini"
-#define HAL_COMMON_DEFAULT_BACKEND_COMPATIBILITY_PATH "/opt/etc/hal/.hal-backend-compatibility"
+#define HAL_CC_DEFAULT_HAL_INFO_INI_PATH "/hal/etc/hal-info.ini"
+#define HAL_CC_DEFAULT_COMPATIBILITY_RESULT_PATH "/opt/etc/hal/.hal-backend-compatibility"
-#define COMPAT_INFO_MODULE_NAME_MAX 64
-#define COMPAT_INFO_COMPAT_DESC_MAX 64
-#define COMPAT_INFO_FILE_ALIGN_BYTE ((COMPAT_INFO_MODULE_NAME_MAX + COMPAT_INFO_COMPAT_DESC_MAX) + 32)
+#define COMPAT_INFO_MODULE_NAME_MAX 64
+#define COMPAT_INFO_COMPAT_DESC_MAX 64
+#define COMPAT_INFO_FILE_ALIGN_BYTE ((COMPAT_INFO_MODULE_NAME_MAX + COMPAT_INFO_COMPAT_DESC_MAX) + 32)
+
+#define HAL_CC_VERSION_UNINITIALIZED (-1)
+
+#define LOAD_FLAG_NO_RELOAD (1 << 0)
+#define STORE_FLAG_NO_OVERWRITE (1 << 0)
struct compatibility_info {
enum hal_module module;
char module_name[COMPAT_INFO_MODULE_NAME_MAX];
- enum hal_common_backend_compatibility compat;
- char compat_desc[COMPAT_INFO_COMPAT_DESC_MAX];
-};
-
-struct compatibility_data {
- enum hal_module module;
- int major;
- int minor;
+ int major_version;
+ int minor_version;
+ const char *error_desc;
};
-static struct compatibility_info g_compatibility_info[HAL_MODULE_END];
-static bool g_compatibility_info_loaded = false;
+static struct compatibility_info g_compatibility_manifest_info[HAL_MODULE_END];
+static bool g_compatibility_manifest_info_loaded = false;
-static void set_compatibility_info_compat(enum hal_module module,
- enum hal_common_backend_compatibility compat, const char *desc)
-{
- if (module < HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END)
- return;
+static struct compatibility_info g_compatibility_backend_info[HAL_MODULE_END];
+static bool g_compatibility_backend_info_loaded = false;
- g_compatibility_info[module].compat = compat;
+static enum hal_common_backend_compatibility g_compatibility_result[HAL_MODULE_END];
+static bool g_compatibility_result_synced = false;
- if (!desc)
- return;
+static enum hal_common_backend_compatibility
+is_manifest_backend_version_compatible(int manifest_major, int manifest_minor,
+ int backend_major, int backend_minor)
+{
+ if (manifest_major == HAL_CC_VERSION_UNINITIALIZED
+ || manifest_minor == HAL_CC_VERSION_UNINITIALIZED
+ || backend_major == HAL_CC_VERSION_UNINITIALIZED
+ || backend_minor == HAL_CC_VERSION_UNINITIALIZED)
+ return HAL_COMMON_BACKEND_COMPATIBILITY_UNKNOWN;
- snprintf(g_compatibility_info[module].compat_desc,
- COMPAT_INFO_COMPAT_DESC_MAX, "%s", desc);
-}
+ if (manifest_major != backend_major)
+ return HAL_COMMON_BACKEND_COMPATIBILITY_INCOMPATIBLE;
-static void init_compatibility_info(enum hal_module module)
-{
- if (module < HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END)
- return;
+ if (manifest_minor < backend_minor)
+ return HAL_COMMON_BACKEND_COMPATIBILITY_INCOMPATIBLE;
- g_compatibility_info[module].module = module;
- snprintf(g_compatibility_info[module].module_name, COMPAT_INFO_MODULE_NAME_MAX,
- "%s", g_hal_module_info[module].module_name ? : "Not defined");
- set_compatibility_info_compat(module, HAL_COMMON_BACKEND_COMPATIBILITY_UNKNOWN,
- "Manifest hasn't specified the module");
+ return HAL_COMMON_BACKEND_COMPATIBILITY_COMPATIBLE;
}
-static int write_compatibility_info(int fd, enum hal_module module)
+static void init_compatibility_info(struct compatibility_info *info)
{
- char buffer[COMPAT_INFO_FILE_ALIGN_BYTE] = { 0 , };
- struct compatibility_info *ci = NULL;
- ssize_t ret;
- int len = 0;
-
- if (fd == -1)
- return -EINVAL;
-
- if (module < HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END)
- return -EINVAL;
-
- ci = &g_compatibility_info[module];
-
- len = snprintf(buffer, sizeof(buffer), "%d:%s:%d:%s\n",
- ci->module, ci->module_name, ci->compat, ci->compat_desc);
-
- ret = write(fd, buffer, len);
- if (ret == -1)
- return -errno;
-
- return 0;
+ assert(info);
+
+ for (enum hal_module module = 0; module < HAL_MODULE_END; ++module) {
+ info[module].module = module;
+ snprintf(info[module].module_name, COMPAT_INFO_MODULE_NAME_MAX,
+ "%s", g_hal_module_info[module].module_name ? : "Not defined");
+ info[module].major_version = HAL_CC_VERSION_UNINITIALIZED;
+ info[module].minor_version = HAL_CC_VERSION_UNINITIALIZED;
+ info[module].error_desc = "Uninitialized module";
+ }
}
-static int parse_directory(const char *manifest_dir, halcc_manifest *manifest)
+static int parse_manifest_directory(const char *manifest_dir, halcc_manifest *manifest)
{
DIR *dir;
int dfd;
return 0;
}
-static enum hal_common_backend_compatibility is_compatible(int manifest_major, int manifest_minor,
- int backend_major, int backend_minor)
-{
- if (manifest_major != backend_major)
- return HAL_COMMON_BACKEND_COMPATIBILITY_INCOMPATIBLE;
-
- if (manifest_minor < backend_minor)
- return HAL_COMMON_BACKEND_COMPATIBILITY_INCOMPATIBLE;
-
- return HAL_COMMON_BACKEND_COMPATIBILITY_COMPATIBLE;
-}
-
-static void make_compatibility_info_specific(struct halcc_hal *hal, void *user_data)
-{
- struct compatibility_data *data = user_data;
- struct __hal_module_info *info = NULL;
- const char *hal_name = NULL;
- const char *module_name = NULL;
- enum hal_module module;
- int manifest_major;
- int manifest_minor;
- int backend_major;
- int backend_minor;
- int ret;
-
- assert(hal);
- assert(data);
-
- module = data->module;
- info = _hal_api_conf_get_module_info(module, NULL);
- if (info == NULL)
- return;
-
- module_name = info->module_name;
-
- if (halcc_hal_get_name(hal, &hal_name) < 0 || hal_name == NULL)
- return;
-
- ret = strncmp(hal_name, module_name, strlen(hal_name) + 1);
- if (ret != 0)
- return;
-
- ret = halcc_hal_get_version(hal, &manifest_major, &manifest_minor, NULL);
- if (ret < 0)
- return;
-
- backend_major = data->major;
- backend_minor = data->minor;
-
- g_compatibility_info[module].compat = is_compatible(manifest_major,
- manifest_minor, backend_major, backend_minor);
-}
-
-static void make_compatibility_info(void *data, void *user_data)
+static void make_compatibility_manifest_info(void *data, void *user_data)
{
enum hal_module module;
halcc_hal *hal;
const char *hal_name = NULL;
int manifest_major, manifest_minor;
- int backend_major, backend_minor;
halcc_dependency_state_e state;
int ret;
- enum hal_common_backend_compatibility compat = HAL_COMMON_BACKEND_COMPATIBILITY_INCOMPATIBLE;
+ const char *error_desc = NULL;
+ struct compatibility_info *manifest_info = NULL;
hal = (halcc_hal *) data;
+ manifest_info = (struct compatibility_info *) user_data;
assert(hal);
-
- if (user_data) { // search for specific objective
- make_compatibility_info_specific(hal, user_data);
- return;
- }
+ assert(manifest_info);
if (halcc_hal_get_name(hal, &hal_name) < 0 || hal_name == NULL)
return;
return;
}
+
if (halcc_hal_get_dependency_state(hal, &state) != 0) {
- set_compatibility_info_compat(module,
- HAL_COMMON_BACKEND_COMPATIBILITY_INCOMPATIBLE,
- "Manifest failed to resolve dependency");
- return;
+ error_desc = "Failed to resolve dependency";
+ goto out;
}
if (halcc_hal_get_version(hal, &manifest_major, &manifest_minor, NULL) < 0) {
- set_compatibility_info_compat(module,
- HAL_COMMON_BACKEND_COMPATIBILITY_INCOMPATIBLE,
- "Manifest has invalid version");
- return;
+ error_desc = "Invalid manifest version";
+ goto out;
}
- ret = hal_common_get_backend_version(module, &backend_major, &backend_minor);
- if (ret < 0) {
- set_compatibility_info_compat(module,
- HAL_COMMON_BACKEND_COMPATIBILITY_INCOMPATIBLE,
- "Backend has invalid version");
- return;
- }
+ manifest_info[module].major_version = manifest_major;
+ manifest_info[module].minor_version = manifest_minor;
- compat = is_compatible(manifest_major, manifest_minor, backend_major, backend_minor);
- if (compat == HAL_COMMON_BACKEND_COMPATIBILITY_COMPATIBLE)
- set_compatibility_info_compat(module,
- HAL_COMMON_BACKEND_COMPATIBILITY_COMPATIBLE,
- "Compatible");
- else
- set_compatibility_info_compat(module,
- HAL_COMMON_BACKEND_COMPATIBILITY_INCOMPATIBLE,
- "Backend has incompatible version");
+out:
+ manifest_info[module].error_desc = error_desc;
}
static int get_tizen_hal_version(int *major, int *minor)
assert(major);
assert(minor);
- fp = fopen(HAL_COMMON_DEFAULT_HAL_INFO_INI, "r");
+ fp = fopen(HAL_CC_DEFAULT_HAL_INFO_INI_PATH, "r");
if (!fp) {
- _E("Failed to open %s, %m\n", HAL_COMMON_DEFAULT_HAL_INFO_INI);
+ _E("Failed to open %s, %m\n", HAL_CC_DEFAULT_HAL_INFO_INI_PATH);
return -errno;
}
return fchown(fd, uid_system_fw, gid_system_fw);
}
-static int store_backend_compatibility_to_storage(bool overwrite)
+static int store_hal_backend_compatibility(struct compatibility_info *manifest_info,
+ struct compatibility_info *backend_info,
+ enum hal_common_backend_compatibility *backend_compatibilities,
+ int store_flag)
{
int fd = -1;
int flag = O_WRONLY | O_CREAT | O_TRUNC;
int ret;
- assert(g_compatibility_info_loaded);
+ assert(g_compatibility_manifest_info_loaded);
+ assert(g_compatibility_backend_info_loaded);
- if (!overwrite)
+ if (store_flag & STORE_FLAG_NO_OVERWRITE)
flag |= O_EXCL;
- fd = open(HAL_COMMON_DEFAULT_BACKEND_COMPATIBILITY_PATH, flag, 0644);
+ fd = open(HAL_CC_DEFAULT_COMPATIBILITY_RESULT_PATH, flag, 0644);
if (fd == -1)
return (errno == EEXIST) ? 0 : -errno;
return ret;
}
- for (enum hal_module module = 0; module < HAL_MODULE_END; ++module)
- write_compatibility_info(fd, module);
+ for (enum hal_module module = 0; module < HAL_MODULE_END; ++module) {
+ char buffer[COMPAT_INFO_FILE_ALIGN_BYTE] = { 0 , };
+ ssize_t ret2;
+ int length = 0;
+ enum hal_common_backend_compatibility compatibility;
+ const char *compatibility_desc = NULL;
+
+ compatibility = backend_compatibilities[module];
+ compatibility_desc = (compatibility == HAL_COMMON_BACKEND_COMPATIBILITY_COMPATIBLE) ?
+ "Compatible" : "Incompatible";
+
+ length = snprintf(buffer, sizeof(buffer), "%d:%s:%d.%d:%d.%d:%s:%s:%s\n",
+ module,
+ manifest_info[module].module_name,
+ manifest_info[module].major_version, manifest_info[module].minor_version,
+ backend_info[module].major_version, backend_info[module].minor_version,
+ manifest_info[module].error_desc ?: "-",
+ backend_info[module].error_desc ?: "-",
+ compatibility_desc);
+
+ ret2 = write(fd, buffer, length);
+ if (ret2 < 0)
+ _W("Failed to write compatibility result(%d)", -errno);
+ }
close(fd);
return 0;
}
-static int load_backend_compatibility_from_manifest(void *data)
+static int load_hal_manifest(struct compatibility_info *manifest_info, int load_flag)
{
char manifest_dir[64] = { 0, };
halcc_manifest *manifest = NULL;
int ret = 0;
+ if (!manifest_info)
+ return -EINVAL;
+
+ if ((load_flag & LOAD_FLAG_NO_RELOAD) && g_compatibility_manifest_info_loaded)
+ return 0;
+
+ init_compatibility_info(manifest_info);
+ g_compatibility_manifest_info_loaded = false;
+
+ g_compatibility_result_synced = false;
+
ret = build_compatibility_manifest_dir(manifest_dir, sizeof(manifest_dir));
if (ret < 0)
return ret;
if (ret < 0)
return ret;
- ret = parse_directory(manifest_dir, manifest);
+ ret = parse_manifest_directory(manifest_dir, manifest);
if (ret < 0)
goto out;
halcc_manifest_validate_hal_dependency(manifest);
- if (data) { // search for specific objective
- halcc_manifest_foreach_hal(manifest, make_compatibility_info, data);
- return 0;
- }
+ halcc_manifest_foreach_hal(manifest, make_compatibility_manifest_info, manifest_info);
- g_compatibility_info_loaded = false;
-
- for (enum hal_module module = 0; module < HAL_MODULE_END; ++module)
- init_compatibility_info(module);
- halcc_manifest_foreach_hal(manifest, make_compatibility_info, NULL);
-
- g_compatibility_info_loaded = true;
+ g_compatibility_manifest_info_loaded = true;
out:
if (manifest)
return ret;
}
-static int load_backend_compatibility_from_storage(void)
+
+static int load_hal_backend_version(struct compatibility_info *backend_info, int load_flag)
+{
+ enum hal_module module;
+ int major_version;
+ int minor_version;
+ int ret;
+
+ if (!backend_info)
+ return -EINVAL;
+
+ if ((load_flag & LOAD_FLAG_NO_RELOAD) && g_compatibility_backend_info_loaded)
+ return 0;
+
+ init_compatibility_info(backend_info);
+ g_compatibility_backend_info_loaded = false;
+
+ g_compatibility_result_synced = false;
+
+ for (module = 0; module < HAL_MODULE_END; ++module) {
+ ret = hal_common_get_backend_version(module, &major_version, &minor_version);
+ if (ret < 0) {
+ _W("Failed to get backend(%s) version(%d)", backend_info[module].module_name, ret);
+ backend_info[module].error_desc = "Invalid backend version";
+ continue;
+ }
+
+ backend_info[module].major_version = major_version;
+ backend_info[module].minor_version = minor_version;
+ backend_info[module].error_desc = NULL;
+ }
+
+ g_compatibility_backend_info_loaded = true;
+
+ return 0;
+}
+
+static int load_hal_manifest_and_hal_backend_version_fallback(struct compatibility_info *manifest_info,
+ struct compatibility_info *backend_info, int load_flag)
+{
+ int ret;
+
+ if (!manifest_info || !backend_info)
+ return -EINVAL;
+
+ ret = load_hal_manifest(manifest_info, load_flag);
+ if (ret < 0)
+ return ret;
+
+ ret = load_hal_backend_version(backend_info, load_flag);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int scanf_hal_backend_compatibility(const char *str,
+ enum hal_module *module,
+ int *manifest_major, int *manifest_minor,
+ int *backend_major, int *backend_minor)
+{
+ enum hal_module tmp_module;
+ int tmp_manifest_major;
+ int tmp_manifest_minor;
+ int tmp_backend_major;
+ int tmp_backend_minor;
+ int ret;
+
+ if (!str)
+ return -EINVAL;
+
+ if (!module
+ || !manifest_major || !manifest_minor
+ || !backend_major || !backend_minor)
+ return -EINVAL;
+
+ ret = sscanf(str, "%d:%*[^:]:%d.%d:%d.%d",
+ (int *) &tmp_module,
+ &tmp_manifest_major, &tmp_manifest_minor,
+ &tmp_backend_major, &tmp_backend_minor);
+ if (ret != 5)
+ return -EINVAL;
+
+ if (tmp_module < 0 || tmp_module >= HAL_MODULE_END)
+ return -EINVAL;
+
+ *module = tmp_module;
+ *manifest_major = tmp_manifest_major;
+ *manifest_minor = tmp_manifest_minor;
+ *backend_major = tmp_backend_major;
+ *backend_minor = tmp_backend_minor;
+
+ return 0;
+}
+
+static int load_hal_backend_compatibility_file(struct compatibility_info *manifest_info,
+ struct compatibility_info *backend_info)
{
FILE *fp = NULL;
char *line = NULL;
size_t len = 0;
- enum hal_module module;
int ret;
- if (g_compatibility_info_loaded)
- return 0;
+ if (!manifest_info || !backend_info)
+ return -EINVAL;
- fp = fopen(HAL_COMMON_DEFAULT_BACKEND_COMPATIBILITY_PATH, "r");
+ fp = fopen(HAL_CC_DEFAULT_COMPATIBILITY_RESULT_PATH, "r");
if (!fp)
return -errno;
- for (module = 0; module < HAL_MODULE_END; ++module)
- init_compatibility_info(module);
+ init_compatibility_info(manifest_info);
+ g_compatibility_manifest_info_loaded = false;
+
+ init_compatibility_info(backend_info);
+ g_compatibility_backend_info_loaded = false;
+
+ g_compatibility_result_synced = false;
- module = 0;
while (getline(&line, &len, fp) != EOF) {
- struct compatibility_info *ci = NULL;
+ enum hal_module module;
+ int manifest_major_version = HAL_CC_VERSION_UNINITIALIZED;
+ int manifest_minor_version = HAL_CC_VERSION_UNINITIALIZED;
+ int backend_major_version = HAL_CC_VERSION_UNINITIALIZED;
+ int backend_minor_version = HAL_CC_VERSION_UNINITIALIZED;
+
+ ret = scanf_hal_backend_compatibility(line,
+ &module,
+ &manifest_major_version, &manifest_minor_version,
+ &backend_major_version, &backend_minor_version);
+ if (ret < 0)
+ continue;
- if (module >= HAL_MODULE_END)
- break;
+ if (manifest_info) {
+ manifest_info[module].major_version = manifest_major_version;
+ manifest_info[module].minor_version = manifest_minor_version;
+ }
- ci = &g_compatibility_info[module++];
- ret = sscanf(line, "%d:%63[^:]:%d:%63s",
- (int *) &ci->module, ci->module_name, (int *) &ci->compat, ci->compat_desc);
- if (ret != 4)
- _E("Failed to load %d module", module);
+ if (backend_info) {
+ backend_info[module].major_version = backend_major_version;
+ backend_info[module].minor_version = backend_minor_version;
+ }
}
free(line);
fclose(fp);
fp = NULL;
- g_compatibility_info_loaded = true;
+ g_compatibility_manifest_info_loaded = true;
+ g_compatibility_backend_info_loaded = true;
return 0;
}
-static int load_backend_compatibility(void *data)
+static int load_hal_manifest_and_hal_backend_version(struct compatibility_info *manifest_info,
+ struct compatibility_info *backend_info, int load_flag)
{
- if (g_compatibility_info_loaded)
- return 0;
+ int ret;
- load_backend_compatibility_from_storage();
- if (g_compatibility_info_loaded)
- return 0;
+ if (!manifest_info || !backend_info)
+ return -EINVAL;
- load_backend_compatibility_from_manifest(data);
- if (g_compatibility_info_loaded)
+ if ((load_flag & LOAD_FLAG_NO_RELOAD)
+ && g_compatibility_manifest_info_loaded
+ && g_compatibility_backend_info_loaded)
return 0;
- return -ENODATA;
+ ret = load_hal_backend_compatibility_file(manifest_info, backend_info);
+ if (ret < 0)
+ return load_hal_manifest_and_hal_backend_version_fallback(manifest_info,
+ backend_info, load_flag);
+
+ return 0;
+}
+
+static int check_hal_backend_compatibility(const struct compatibility_info *manifest_info,
+ const struct compatibility_info *backend_info,
+ enum hal_common_backend_compatibility *backend_compatibilities)
+{
+ assert(manifest_info);
+ assert(backend_info);
+ assert(backend_compatibilities);
+
+ if (g_compatibility_result_synced)
+ return 0;
+
+ for (enum hal_module module = 0; module < HAL_MODULE_END; ++module)
+ backend_compatibilities[module] = is_manifest_backend_version_compatible(
+ manifest_info[module].major_version, manifest_info[module].minor_version,
+ backend_info[module].major_version, backend_info[module].minor_version);
+
+ g_compatibility_result_synced = true;
+
+ return 0;
}
-int hal_api_cc_check_backend_compatibility_all(
- enum hal_common_backend_compatibility **backend_compatibilities, int *length)
+static int check_backend_compatibility_all(
+ const enum hal_common_backend_compatibility **backend_compatibilities)
{
int ret;
- enum hal_common_backend_compatibility *arr = NULL;
- ret = load_backend_compatibility(NULL);
+ if (!backend_compatibilities)
+ return -EINVAL;
+
+ ret = load_hal_manifest_and_hal_backend_version(g_compatibility_manifest_info,
+ g_compatibility_backend_info, LOAD_FLAG_NO_RELOAD);
if (ret < 0)
return ret;
- ret = store_backend_compatibility_to_storage(false);
+ ret = check_hal_backend_compatibility(g_compatibility_manifest_info,
+ g_compatibility_backend_info, g_compatibility_result);
if (ret < 0)
return ret;
- if (!backend_compatibilities)
- return 0;
-
- if (!length)
- return -EINVAL;
-
- arr = calloc(HAL_MODULE_END, sizeof(enum hal_common_backend_compatibility));
- if (!arr)
- return -ENOMEM;
-
- for (int i = 0; i < HAL_MODULE_END; ++i)
- arr[i] = g_compatibility_info[i].compat;
+ ret = store_hal_backend_compatibility(g_compatibility_manifest_info,
+ g_compatibility_backend_info, g_compatibility_result, STORE_FLAG_NO_OVERWRITE);
+ if (ret < 0)
+ return ret;
- *length = HAL_MODULE_END;
- *backend_compatibilities = arr;
- arr = NULL;
+ *backend_compatibilities = g_compatibility_result;
return 0;
}
enum hal_common_backend_compatibility *backend_compatibility)
{
int ret;
+ const enum hal_common_backend_compatibility *backend_compatibilities = NULL;
if (module < HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END)
return -EINVAL;
if (!backend_compatibility)
return -EINVAL;
- ret = load_backend_compatibility(NULL);
+ ret = check_backend_compatibility_all(&backend_compatibilities);
if (ret < 0)
return ret;
- ret = store_backend_compatibility_to_storage(false);
- if (ret < 0)
- return ret;
+ assert(backend_compatibilities);
- *backend_compatibility = g_compatibility_info[module].compat;
+ *backend_compatibility = backend_compatibilities[module];
return 0;
}
{
int ret;
- struct compatibility_data data = {
- .module = module,
- .major = backend_major,
- .minor = backend_minor,
- };
+ if (module < HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END)
+ return -EINVAL;
+
+ if (!backend_compatibility)
+ return -EINVAL;
- ret = load_backend_compatibility(&data);
+ ret = load_hal_manifest(g_compatibility_manifest_info, LOAD_FLAG_NO_RELOAD);
if (ret < 0)
return ret;
- *backend_compatibility = g_compatibility_info[module].compat;
+ *backend_compatibility = is_manifest_backend_version_compatible(
+ g_compatibility_manifest_info[module].major_version,
+ g_compatibility_manifest_info[module].minor_version,
+ backend_major,
+ backend_minor);
return 0;
}