halcc: Rework halcc compatibility checker 82/311182/9
authorYoungjae Cho <y0.cho@samsung.com>
Tue, 14 May 2024 08:39:01 +0000 (17:39 +0900)
committerYoungjae Cho <y0.cho@samsung.com>
Mon, 20 May 2024 05:57:41 +0000 (14:57 +0900)
 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 <y0.cho@samsung.com>
packaging/systemd-hal-compatibility-checker-generator
src/common.h
src/hal-api-compatibility-checker-object.c
src/hal-api-compatibility-checker-object.h
src/hal-api-compatibility-checker-parser.c
src/hal-api-compatibility-checker.c
src/hal-api-compatibility-checker.h

index 5cc97d971c43d2093192b50370a67080795fe19c..05ccf768d9e6c5b5dc1b20fd0a961536e78fcafc 100644 (file)
@@ -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
index 03b25647ce1c65114a097cbbcda18bf954644d47..8b3a3075d47b0f68306b8b60fdf6a5b46c49d434 100644 (file)
@@ -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,
index 5d076dd390f0e23884776b2639db596d2ec468b6..6dffe7380b13642ad53121b75e007b90cdbc288f 100644 (file)
@@ -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;
index e5885258d5f2a0a0a2a4ddc5957d81369da8fe79..43492c156bd4a349bba62343f23f9de8c3cf4405 100644 (file)
@@ -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);
index c2fcd866cf2f449ba8bc821289a92d31b3bb1670..63da72e3aa5b28eef52e9619b9abdcd4380092c9 100644 (file)
@@ -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);
 
index e7b6fe52bca6be1270f0689055e0dd9a89c52370..aa5a0c6be03b7276811b159b0ef445b66ddc0269 100644 (file)
 #include <hal-common.h>
 
 #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;
 }
index a3b5097a3ab21cc95d0ce697322d1bf813e6d5d6..07d029e7e539e3fcce796a384e3c6ac09d4076c4 100644 (file)
 
 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__