From: Youngjae Cho Date: Tue, 14 May 2024 08:39:01 +0000 (+0900) Subject: halcc: Rework halcc compatibility checker X-Git-Tag: accepted/tizen/unified/20240611.122614~6 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cb249725fe725fa2a4cfc63a0c1b0cea3eaa9c0d;p=platform%2Fhal%2Fapi%2Fcommon.git halcc: Rework halcc compatibility checker As compatibility manifest has changed to specify multiple version for hal, the halcc compatibility checker has also been fixed to follow that scheme. 1. The result file format has changed so that the halcc can now randomly access to module index for which the halcc has requested. 2. Operation for generating result file will be rejected unless it is invoked by generator of systemd system manager. Therefore, if there is no result file when checking compatibility, and it is not on generator context, compatibility checking will do the entire routine, for every invocation, that should have done when creating the result file. 3. For updating manifest file from a hal api repository, add below command at %post rpm scriptlet. : rm -rf /opt/etc/hal/.hal-backend-compatibility : systemctl daemon-reload systemctl daemon-reload triggers generator so it is able to create a new result file from updated manifest. Change-Id: Ia8b140c2edc8d6de3c205716b8bed7d0fc92f602 Signed-off-by: Youngjae Cho --- diff --git a/packaging/systemd-hal-compatibility-checker-generator b/packaging/systemd-hal-compatibility-checker-generator index 5cc97d9..05ccf76 100644 --- a/packaging/systemd-hal-compatibility-checker-generator +++ b/packaging/systemd-hal-compatibility-checker-generator @@ -2,4 +2,12 @@ PATH=/bin:/usr/bin:/sbin:/usr/sbin +# FIXME: Remove SYSTEMD_SCOPE after upgrading systemd version beyond 251. +# +# As of systemd version 251, systemd sets this environment variable to "system" +# if it is invoked from generator of system service manager. But we are currently +# on version 244 so manually set the variable to inform the binary that it is +# generator context of system service manager. +export SYSTEMD_SCOPE=system + hal-compatibility-checker --skip-if-result-exist --redirect-all=/dev/kmsg diff --git a/src/common.h b/src/common.h index 03b2564..8b3a307 100644 --- a/src/common.h +++ b/src/common.h @@ -43,8 +43,9 @@ extern "C" { #define _E(fmt, args...) do { } while(0) #endif -#define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0])) +#define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0])) #define HALCC_NAME_MAX 128 +#define HALCC_NUM_VERSION_LIST_MAX 8 enum hal_license { HAL_LICENSE_UNKNOWN = 0, diff --git a/src/hal-api-compatibility-checker-object.c b/src/hal-api-compatibility-checker-object.c index 5d076dd..6dffe73 100644 --- a/src/hal-api-compatibility-checker-object.c +++ b/src/hal-api-compatibility-checker-object.c @@ -29,7 +29,6 @@ #include "hal-api-compatibility-checker-parser.h" #define HALCC_TRANSPORT_DEFAULT HALCC_TRANSPORT_PASSTHROUGH -#define MAX_NUM_VERSION 8 typedef struct halcc_version { int major; @@ -43,9 +42,8 @@ typedef struct halcc_interface { typedef struct halcc_hal { char *name; - halcc_version version_list[MAX_NUM_VERSION]; - int num_version; - halcc_version version; + halcc_version version_list[HALCC_NUM_VERSION_LIST_MAX]; + int num_version_list; halcc_transport_e transport; GHashTable *interfaces; } halcc_hal; @@ -406,14 +404,7 @@ int halcc_hal_get_name(halcc_hal *hal, const char **hal_name) return 0; } - -/** - * FIXME: It manages list of versions internally, but it only - * exposes the first incoming version as a representative version for the hal, - * and the halcc_hal_get_version(), in turn, will return the version. - * This will be fixed to manage the entire list for counting compatibility. - */ -int halcc_hal_set_version(halcc_hal *hal, int major, int minor) +int halcc_hal_add_version(halcc_hal *hal, int major, int minor) { int i; @@ -422,16 +413,9 @@ int halcc_hal_set_version(halcc_hal *hal, int major, int minor) return -EINVAL; } - assert(hal->num_version <= MAX_NUM_VERSION); - - - /* FIXME: Only the first incoming version sets hal version */ - if (hal->num_version == 0) { - hal->version.major = major; - hal->version.minor = minor; - } + assert(hal->num_version_list <= HALCC_NUM_VERSION_LIST_MAX); - for (i = 0; i < hal->num_version; ++i) { + for (i = 0; i < hal->num_version_list; ++i) { if (hal->version_list[i].major != major) continue; @@ -441,29 +425,37 @@ int halcc_hal_set_version(halcc_hal *hal, int major, int minor) break; } - if (hal->num_version > i) + if (hal->num_version_list > i) return 0; - if (hal->num_version >= MAX_NUM_VERSION) + if (hal->num_version_list >= HALCC_NUM_VERSION_LIST_MAX) return -EOVERFLOW; - hal->version_list[hal->num_version].major = major; - hal->version_list[hal->num_version].minor = minor; + hal->version_list[hal->num_version_list].major = major; + hal->version_list[hal->num_version_list].minor = minor; - hal->num_version += 1; + hal->num_version_list += 1; return 0; } -int halcc_hal_get_version(halcc_hal *hal, int *major, int *minor) +int halcc_hal_get_version_list(halcc_hal *hal, int version_list[][2], + int max_num_version_list, int *num_version_list) { - if (!hal || !major || !minor) { - printf("Invalid parameter\n"); + if (!hal || !num_version_list) return -EINVAL; + + for (int i = 0; i < max_num_version_list && i < hal->num_version_list; ++i) { + version_list[i][0] = hal->version_list[i].major; + version_list[i][1] = hal->version_list[i].minor; + } + + if (hal->num_version_list > max_num_version_list) { + *num_version_list = max_num_version_list; + return -EOVERFLOW; } - *major = hal->version.major; - *minor = hal->version.minor; + *num_version_list = hal->num_version_list; return 0; } @@ -533,7 +525,7 @@ bool halcc_hal_is_compatible_with_version(halcc_hal *hal, int major, int minor) return false; } - for (int i = 0; i < hal->num_version; ++i) { + for (int i = 0; i < hal->num_version_list; ++i) { if (hal->version_list[i].major != major) { printf("Major not matched\n"); continue; diff --git a/src/hal-api-compatibility-checker-object.h b/src/hal-api-compatibility-checker-object.h index e588525..43492c1 100644 --- a/src/hal-api-compatibility-checker-object.h +++ b/src/hal-api-compatibility-checker-object.h @@ -56,8 +56,9 @@ int halcc_hal_new(halcc_hal **hal); void halcc_hal_free(halcc_hal *hal); int halcc_hal_set_name(halcc_hal *hal, const char *hal_name); int halcc_hal_get_name(halcc_hal *hal, const char **hal_name); -int halcc_hal_set_version(halcc_hal *hal, int major, int minor); -int halcc_hal_get_version(halcc_hal *hal, int *major, int *minor); +int halcc_hal_add_version(halcc_hal *hal, int major, int minor); +int halcc_hal_get_version_list(halcc_hal *hal, + int version_list[][2], int max_num_version_list, int *num_version_list); int halcc_hal_set_transport(halcc_hal *hal, halcc_transport_e transport); int halcc_hal_get_transport(halcc_hal *hal, halcc_transport_e *transport); int halcc_hal_add_interface(halcc_hal *hal, halcc_interface *interface); diff --git a/src/hal-api-compatibility-checker-parser.c b/src/hal-api-compatibility-checker-parser.c index c2fcd86..63da72e 100644 --- a/src/hal-api-compatibility-checker-parser.c +++ b/src/hal-api-compatibility-checker-parser.c @@ -114,9 +114,9 @@ static int parse_hal(xmlNode *node, halcc_manifest *manifest) continue; } - ret = halcc_hal_set_version(hal, major, minor); + ret = halcc_hal_add_version(hal, major, minor); if (ret != 0) - printf("Failed to halcc_hal_set_version(), ret=%d\n", ret); + printf("Failed to halcc_hal_add_version(), ret=%d\n", ret); } else if (xmlStrEqual(child->name, "transport")) { __xmlchar__ xmlChar *transport = xmlNodeGetContent(child); diff --git a/src/hal-api-compatibility-checker.c b/src/hal-api-compatibility-checker.c index e7b6fe5..aa5a0c6 100644 --- a/src/hal-api-compatibility-checker.c +++ b/src/hal-api-compatibility-checker.c @@ -29,75 +29,23 @@ #include #include "common.h" -#include "hal-api-list.h" #include "hal-api-conf.h" #include "hal-api-compatibility-checker.h" #include "hal-api-compatibility-checker-object.h" #include "hal-api-compatibility-checker-parser.h" -#define HAL_CC_DEFAULT_HAL_INFO_INI_PATH "/hal/etc/hal-info.ini" #define HAL_CC_DEFAULT_HAL_MANIFEST_DIR "/etc/hal-manifest" #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 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]; - int major_version; - int minor_version; - const char *error_desc; + int version_list[HALCC_NUM_VERSION_LIST_MAX][2]; + int num_version_list; + enum hal_common_backend_compatibility compatibility; }; -static struct compatibility_info g_compatibility_manifest_info[HAL_MODULE_END]; -static bool g_compatibility_manifest_info_loaded = false; - -static struct compatibility_info g_compatibility_backend_info[HAL_MODULE_END]; -static bool g_compatibility_backend_info_loaded = false; - -static enum hal_common_backend_compatibility g_compatibility_result[HAL_MODULE_END]; -static bool g_compatibility_result_synced = false; - -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; - - 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 init_compatibility_info(struct compatibility_info *info) -{ - 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_manifest_directory(const char *manifest_dir, halcc_manifest *manifest) { DIR *dir; @@ -143,52 +91,30 @@ static int parse_manifest_directory(const char *manifest_dir, halcc_manifest *ma return 0; } -static void make_compatibility_manifest_info(void *data, void *user_data) +static int get_module_by_name(const char *name, enum hal_module *module) { - enum hal_module module; - halcc_hal *hal; - const char *hal_name = NULL; - int manifest_major, manifest_minor; int ret; - const char *error_desc = NULL; - struct compatibility_info *manifest_info = NULL; - - hal = (halcc_hal *) data; - manifest_info = (struct compatibility_info *) user_data; - - assert(hal); - assert(manifest_info); - if (halcc_hal_get_name(hal, &hal_name) < 0 || hal_name == NULL) - return; + if (!name || !module) + return -EINVAL; - for (module = HAL_MODULE_UNKNOWN; module < HAL_MODULE_END; ++module) { + for (int i = HAL_MODULE_UNKNOWN; i < HAL_MODULE_END; ++i) { char module_name[128] = { 0 , }; - ret = hal_common_get_backend_module_name(module, module_name, sizeof(module_name)); + ret = hal_common_get_backend_module_name(i, module_name, sizeof(module_name)); if (ret < 0) continue; - ret = strncmp(hal_name, module_name, strlen(hal_name) + 1); - if (ret == 0) - break; - } + ret = strncmp(name, module_name, strlen(name) + 1); + if (ret != 0) + continue; - if (module >= HAL_MODULE_END) { - _E("Unknown hal module: %s\n", hal_name); - return; - } + *module = i; - if (halcc_hal_get_version(hal, &manifest_major, &manifest_minor) < 0) { - error_desc = "Invalid manifest version"; - goto out; + return 0; } - manifest_info[module].major_version = manifest_major; - manifest_info[module].minor_version = manifest_minor; - -out: - manifest_info[module].error_desc = error_desc; + return -EINVAL; } static int set_owner(int fd) @@ -280,316 +206,198 @@ static int set_owner(int fd) return fchown(fd, uid_system_fw, gid_system_fw); } -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) +static void __convert_hal_to_info(void *data_hal, void *data_info, bool skip_version_check) { - int fd = -1; - int flag = O_WRONLY | O_CREAT | O_TRUNC; + halcc_hal *hal; + struct compatibility_info *info; + enum hal_module module; + const char *hal_name = NULL; + unsigned int major, minor; int ret; - assert(g_compatibility_manifest_info_loaded); - assert(g_compatibility_backend_info_loaded); + hal = (halcc_hal *) data_hal; + info = (struct compatibility_info *) data_info; - if (store_flag & STORE_FLAG_NO_OVERWRITE) - flag |= O_EXCL; - - fd = open(HAL_CC_DEFAULT_COMPATIBILITY_RESULT_PATH, flag, 0644); - if (fd == -1) - return (errno == EEXIST) ? 0 : -errno; - - ret = set_owner(fd); // system_fw:system_fw - if (ret < 0) { - close(fd); - return ret; - } - - 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_hal_manifest(struct compatibility_info *manifest_info, int load_flag) -{ - halcc_manifest *manifest = NULL; - int ret = 0; - - if (!manifest_info) - return -EINVAL; + assert(hal); + assert(info); - if ((load_flag & LOAD_FLAG_NO_RELOAD) && g_compatibility_manifest_info_loaded) - return 0; + ret = halcc_hal_get_name(hal, &hal_name); + if (ret < 0) + return; - init_compatibility_info(manifest_info); - g_compatibility_manifest_info_loaded = false; + ret = get_module_by_name(hal_name, &module); + if (ret < 0) + return; - g_compatibility_result_synced = false; + assert(module >= HAL_MODULE_UNKNOWN); + assert(module < HAL_MODULE_END); - ret = halcc_manifest_new(&manifest); - if (ret < 0) - return ret; + info += module; - ret = parse_manifest_directory(HAL_CC_DEFAULT_HAL_MANIFEST_DIR, manifest); + strncpy(info->module_name, hal_name, COMPAT_INFO_MODULE_NAME_MAX - 1); + ret = halcc_hal_get_version_list(hal, info->version_list, + sizeof(info->version_list) / sizeof(info->version_list[0]), + &info->num_version_list); if (ret < 0) - goto out; - - halcc_manifest_foreach_hal(manifest, make_compatibility_manifest_info, manifest_info); + return; - g_compatibility_manifest_info_loaded = true; + /** + * hal_common_get_backend_version() will acquire lock, but this subroutine + * might have locked already if was triggered from hal_common_get_backend(). + * + * For such case, here make escape condition not to fall into deadlock. + */ + if (skip_version_check) + return; -out: - if (manifest) - halcc_manifest_free(g_steal_pointer(&manifest)); + info->compatibility = HAL_COMMON_BACKEND_COMPATIBILITY_INCOMPATIBLE; + ret = hal_common_get_backend_version(module, &major, &minor); + if (ret < 0) + return; - return ret; + if (halcc_hal_is_compatible_with_version(hal, major, minor)) + info->compatibility = HAL_COMMON_BACKEND_COMPATIBILITY_COMPATIBLE; } - -static int load_hal_backend_version(struct compatibility_info *backend_info, int load_flag) +static void convert_hal_to_info(void *data_hal, void *data_info) { - 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; + __convert_hal_to_info(data_hal, data_info, false); } -static int load_hal_manifest_and_hal_backend_version_fallback(struct compatibility_info *manifest_info, - struct compatibility_info *backend_info, int load_flag) +static void convert_hal_to_info_skip_version_check(void *data_hal, void *data_info) { - 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; + __convert_hal_to_info(data_hal, data_info, true); } -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) +static bool is_system_generator_context(void) { - 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; + char *systemd_scope = NULL; + + /** + * If the generator is invoked from the system service manager this variable + * is set to "system"; if invoked from the per-user service manager it is set to "user". + * + * Added in systemd version 251. + */ + systemd_scope = getenv("SYSTEMD_SCOPE"); + + if (!systemd_scope) { + _E("Reject to create %s, not a generator context", + HAL_CC_DEFAULT_COMPATIBILITY_RESULT_PATH); + return false; + } - *module = tmp_module; - *manifest_major = tmp_manifest_major; - *manifest_minor = tmp_manifest_minor; - *backend_major = tmp_backend_major; - *backend_minor = tmp_backend_minor; + if (strncmp(systemd_scope, "system", sizeof("system")) != 0) { + _E("Reject to create %s, only system servie manager is allowed to do it", + HAL_CC_DEFAULT_COMPATIBILITY_RESULT_PATH); + return false; + } - return 0; + return true; } -static int load_hal_backend_compatibility_file(struct compatibility_info *manifest_info, - struct compatibility_info *backend_info) +static int write_comaptibility_info(struct compatibility_info *info, int entry_size) { - FILE *fp = NULL; - char *line = NULL; - size_t len = 0; + int fd = -1; int ret; + ssize_t n_write; - if (!manifest_info || !backend_info) - return -EINVAL; - - fp = fopen(HAL_CC_DEFAULT_COMPATIBILITY_RESULT_PATH, "r"); - if (!fp) + fd = open(HAL_CC_DEFAULT_COMPATIBILITY_RESULT_PATH, + O_WRONLY | O_CREAT | O_EXCL, 0644); + if (fd == -1) { + _E("Failed to create %s, %m", + HAL_CC_DEFAULT_COMPATIBILITY_RESULT_PATH); return -errno; + } - 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; - - while (getline(&line, &len, fp) != EOF) { - 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 (manifest_info) { - manifest_info[module].major_version = manifest_major_version; - manifest_info[module].minor_version = manifest_minor_version; - } - - if (backend_info) { - backend_info[module].major_version = backend_major_version; - backend_info[module].minor_version = backend_minor_version; - } + ret = set_owner(fd); // system_fw:system_fw + if (ret < 0) { + _E("Failed to set owner"); + close(fd); + return ret; } - free(line); - line = NULL; - fclose(fp); - fp = NULL; + n_write = write(fd, info, sizeof(struct compatibility_info) * entry_size); + if (n_write == -1) { + _E("Failed to write info, %m"); + close(fd); + return -errno; + } - g_compatibility_manifest_info_loaded = true; - g_compatibility_backend_info_loaded = true; + close(fd); return 0; } -static int load_hal_manifest_and_hal_backend_version(struct compatibility_info *manifest_info, - struct compatibility_info *backend_info, int load_flag) +static int load_module_compatibility_info(enum hal_module module, + struct compatibility_info *info) { - int ret; + int fd = -1; + size_t n_read = -1; + off_t offset; - if (!manifest_info || !backend_info) + if (module < HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) return -EINVAL; - if ((load_flag & LOAD_FLAG_NO_RELOAD) - && g_compatibility_manifest_info_loaded - && g_compatibility_backend_info_loaded) - return 0; - - 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 (!info) + return -EINVAL; - if (g_compatibility_result_synced) - return 0; + fd = open(HAL_CC_DEFAULT_COMPATIBILITY_RESULT_PATH, O_RDONLY, 0); + if (fd == -1) + return -errno; - 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); + offset = sizeof(struct compatibility_info) * module; + n_read = pread(fd, info, sizeof(*info), offset); + if (n_read == -1) { + close(fd); + return -errno; + } - g_compatibility_result_synced = true; + close(fd); return 0; } -static int check_backend_compatibility_all( - const enum hal_common_backend_compatibility **backend_compatibilities) +static int load_module_compatibility_info_fallback(enum hal_module module, + struct compatibility_info *info, bool skip_version_check) { + halcc_manifest *manifest = NULL; + struct compatibility_info infos[HAL_MODULE_END] = { 0 , }; int ret; - if (!backend_compatibilities) - return -EINVAL; + assert(module >= HAL_MODULE_UNKNOWN); + assert(module < HAL_MODULE_END); + assert(info); - ret = load_hal_manifest_and_hal_backend_version(g_compatibility_manifest_info, - g_compatibility_backend_info, LOAD_FLAG_NO_RELOAD); + ret = halcc_manifest_new(&manifest); if (ret < 0) return ret; - ret = check_hal_backend_compatibility(g_compatibility_manifest_info, - g_compatibility_backend_info, g_compatibility_result); - if (ret < 0) + ret = parse_manifest_directory(HAL_CC_DEFAULT_HAL_MANIFEST_DIR, manifest); + if (ret < 0) { + halcc_manifest_free(manifest); return ret; + } - 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; + if (skip_version_check) + halcc_manifest_foreach_hal(manifest, convert_hal_to_info_skip_version_check, infos); + else + halcc_manifest_foreach_hal(manifest, convert_hal_to_info, infos); + + *info = infos[module]; - *backend_compatibilities = g_compatibility_result; + halcc_manifest_free(manifest); + manifest = NULL; + + /* Writing result is only allowed on system generator context */ + if (!is_system_generator_context()) + return 0; + + /* Incomplete data, no versions. Don't write it */ + if (skip_version_check) + return 0; + + write_comaptibility_info(infos, HAL_MODULE_END); return 0; } @@ -598,7 +406,7 @@ int hal_api_cc_check_backend_compatibility(enum hal_module module, enum hal_common_backend_compatibility *backend_compatibility) { int ret; - const enum hal_common_backend_compatibility *backend_compatibilities = NULL; + struct compatibility_info info = { 0 , }; if (module < HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) return -EINVAL; @@ -606,22 +414,24 @@ int hal_api_cc_check_backend_compatibility(enum hal_module module, if (!backend_compatibility) return -EINVAL; - ret = check_backend_compatibility_all(&backend_compatibilities); - if (ret < 0) - return ret; - - assert(backend_compatibilities); + ret = load_module_compatibility_info(module, &info); + if (ret < 0) { + ret = load_module_compatibility_info_fallback(module, &info, false); + if (ret < 0) + return ret; + } - *backend_compatibility = backend_compatibilities[module]; + *backend_compatibility = info.compatibility; return 0; } int hal_api_cc_check_backend_compatibility_by_version(enum hal_module module, - int backend_major, int backend_minor, + unsigned int major, unsigned int minor, enum hal_common_backend_compatibility *backend_compatibility) { int ret; + struct compatibility_info info = { 0 , }; if (module < HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) return -EINVAL; @@ -629,15 +439,30 @@ int hal_api_cc_check_backend_compatibility_by_version(enum hal_module module, if (!backend_compatibility) return -EINVAL; - ret = load_hal_manifest(g_compatibility_manifest_info, LOAD_FLAG_NO_RELOAD); - if (ret < 0) - return ret; + ret = load_module_compatibility_info(module, &info); + if (ret < 0) { + ret = load_module_compatibility_info_fallback(module, &info, true); + if (ret < 0) + return ret; + } + + *backend_compatibility = HAL_COMMON_BACKEND_COMPATIBILITY_UNKNOWN; + + if (info.num_version_list == 0) + return 0; + + for (int i = 0; i < info.num_version_list; ++i) { + if (info.version_list[i][0] != major) + continue; + + if (info.version_list[i][1] < minor) + continue; + + *backend_compatibility = HAL_COMMON_BACKEND_COMPATIBILITY_COMPATIBLE; + return 0; + } - *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); + *backend_compatibility = HAL_COMMON_BACKEND_COMPATIBILITY_INCOMPATIBLE; return 0; } diff --git a/src/hal-api-compatibility-checker.h b/src/hal-api-compatibility-checker.h index a3b5097..07d029e 100644 --- a/src/hal-api-compatibility-checker.h +++ b/src/hal-api-compatibility-checker.h @@ -21,16 +21,8 @@ int hal_api_cc_check_backend_compatibility(enum hal_module module, enum hal_common_backend_compatibility *backend_compatibility); - -/** - * Special variant of checking compatibility, only for internal use. (Workaround) - * - * It prevents self-blocking due to G_LOCK(hal_common_lock). - * It occurs when __get_backend() is followed by __get_backend_data() within - * its subroutine. - */ int hal_api_cc_check_backend_compatibility_by_version(enum hal_module module, - int backend_major, int backend_minor, + unsigned int major, unsigned int minor, enum hal_common_backend_compatibility *backend_compatibility); #endif // __HAL_API_COMPATIBILITY_CHECKER_H__