Make UUIDs and GUIDs first class citizens for parameters by adding
dedicated dev_add_param_guid/uuid functions as well as globalvar_
wrappers.

We add different functions for both UUID and GUID to handle the
difference in string representation.

Signed-off-by: Ahmad Fatoum <[email protected]>
---
 common/globalvar.c      | 40 +++++++++++++++++
 include/globalvar.h     | 12 ++++++
 include/linux/sprintf.h |  3 ++
 include/param.h         | 39 +++++++++++++++++
 lib/parameter.c         | 95 +++++++++++++++++++++++++++++++++++++++++
 lib/vsprintf.c          |  2 +-
 6 files changed, 190 insertions(+), 1 deletion(-)

diff --git a/common/globalvar.c b/common/globalvar.c
index fcaa15179f68..1fac891ae073 100644
--- a/common/globalvar.c
+++ b/common/globalvar.c
@@ -672,6 +672,46 @@ int globalvar_add_simple_ip(const char *name, IPaddr_t *ip)
        return 0;
 }
 
+int globalvar_add_simple_uuid(const char *name, uuid_t *uuid)
+{
+       struct param_d *p;
+       int ret;
+
+       ret = globalvar_remove_unqualified(name);
+       if (ret)
+               return ret;
+
+       p = dev_add_param_uuid(&global_device, name,
+                              NULL, NULL, uuid, 0);
+
+       if (IS_ERR(p))
+               return PTR_ERR(p);
+
+       globalvar_nv_sync(name);
+
+       return 0;
+}
+
+int globalvar_add_simple_guid(const char *name, guid_t *guid)
+{
+       struct param_d *p;
+       int ret;
+
+       ret = globalvar_remove_unqualified(name);
+       if (ret)
+               return ret;
+
+       p = dev_add_param_guid(&global_device, name,
+                              NULL, NULL, guid, 0);
+
+       if (IS_ERR(p))
+               return PTR_ERR(p);
+
+       globalvar_nv_sync(name);
+
+       return 0;
+}
+
 static int globalvar_init(void)
 {
        const char *endianness;
diff --git a/include/globalvar.h b/include/globalvar.h
index d0a8272588b4..e369616c632a 100644
--- a/include/globalvar.h
+++ b/include/globalvar.h
@@ -5,6 +5,7 @@
 #include <param.h>
 #include <driver.h>
 #include <linux/err.h>
+#include <linux/uuid.h>
 #include <stringlist.h>
 
 extern struct device global_device;
@@ -36,6 +37,8 @@ int globalvar_add_simple_enum(const char *name,       int 
*value,
 int globalvar_add_simple_bitmask(const char *name, unsigned long *value,
                                 const char * const *names, int max);
 int globalvar_add_simple_ip(const char *name, IPaddr_t *ip);
+int globalvar_add_simple_uuid(const char *name, uuid_t *uuid);
+int globalvar_add_simple_guid(const char *name, guid_t *guid);
 
 int nvvar_load(void);
 void nvvar_print(void);
@@ -101,6 +104,15 @@ static inline int globalvar_add_simple_ip(const char *name,
        return 0;
 }
 
+static inline int globalvar_add_simple_uuid(const char *name, uuid_t *uuid)
+{
+       return 0;
+}
+static inline int globalvar_add_simple_guid(const char *name, guid_t *guid)
+{
+       return 0;
+}
+
 static inline void globalvar_remove(const char *name) {}
 
 static inline void globalvar_print(void) {}
diff --git a/include/linux/sprintf.h b/include/linux/sprintf.h
index 349773d3e16a..e4b3df959a72 100644
--- a/include/linux/sprintf.h
+++ b/include/linux/sprintf.h
@@ -43,6 +43,9 @@ static inline __printf(2, 3) int rasprintf(char **strp, const 
char *fmt, ...)
 
 #define basprintf xasprintf
 
+char *uuid_string(char *buf, const char *end, const u8 *addr, int field_width,
+                 int precision, int flags, const char *fmt);
 const char *size_human_readable(unsigned long long size);
 
+
 #endif /* _LINUX_KERNEL_SPRINTF_H */
diff --git a/include/param.h b/include/param.h
index 1713a18c378e..c223114fbde1 100644
--- a/include/param.h
+++ b/include/param.h
@@ -5,6 +5,7 @@
 #include <linux/err.h>
 #include <linux/types.h>
 #include <linux/list.h>
+#include <linux/uuid.h>
 #include <bobject.h>
 #include <stdarg.h>
 
@@ -27,6 +28,8 @@ enum param_type {
        PARAM_TYPE_IPV4,
        PARAM_TYPE_MAC,
        PARAM_TYPE_FILE_LIST,
+       PARAM_TYPE_UUID,
+       PARAM_TYPE_GUID,
 };
 
 struct param_d {
@@ -106,6 +109,12 @@ struct param_d *bobject_add_param_file_list(bobject_t 
bobj, const char *name,
                                        struct file_list **file_list,
                                        void *priv);
 
+struct param_d *__bobject_add_param_uuid(bobject_t _bobj, const char *name,
+                                        int (*set)(struct param_d *p, void 
*priv),
+                                        int (*get)(struct param_d *p, void 
*priv),
+                                        void *uuid, bool is_guid,
+                                        void *priv);
+
 struct param_d *vbobject_add_param_fixed(struct bobject *bobj, const char 
*name,
                                         const char *fmt, va_list ap);
 
@@ -233,6 +242,15 @@ static inline struct param_d 
*bobject_add_param_file_list(bobject_t bobj,
        return NULL;
 }
 
+static inline struct param_d *__bobject_add_param_uuid(bobject_t _bobj, const 
char *name,
+                                                      int (*set)(struct 
param_d *p, void *priv),
+                                                      int (*get)(struct 
param_d *p, void *priv),
+                                                      void *uuid, bool is_guid,
+                                                      void *priv)
+{
+       return NULL;
+}
+
 static inline
 struct param_d *vbobject_add_param_fixed(struct bobject *bobj, const char 
*name,
                                         const char *fmt, va_list ap)
@@ -273,6 +291,25 @@ static inline const char *get_param_value(struct param_d 
*param)
        return param->get(param->bobj, param);
 }
 
+static inline struct param_d *
+bobject_add_param_uuid(bobject_t _bobj, const char *name,
+                      int (*set)(struct param_d *p, void *priv),
+                      int (*get)(struct param_d *p, void *priv),
+                      uuid_t *uuid, void *priv)
+{
+       return __bobject_add_param_uuid(_bobj, name, set, get, uuid, false, 
priv);
+}
+
+static inline struct param_d *
+bobject_add_param_guid(bobject_t _bobj, const char *name,
+                      int (*set)(struct param_d *p, void *priv),
+                      int (*get)(struct param_d *p, void *priv),
+                      guid_t *guid, void *priv)
+{
+       return __bobject_add_param_uuid(_bobj, name, set, get, guid, true, 
priv);
+}
+
+
 int param_set_readonly(struct param_d *p, void *priv);
 
 /*
@@ -409,6 +446,8 @@ static inline struct param_d 
*bobject_add_param_bitmask_ro(bobject_t bobj,
 #define dev_add_param_ip               bobject_add_param_ip
 #define dev_add_param_mac              bobject_add_param_mac
 #define dev_add_param_file_list                bobject_add_param_file_list
+#define dev_add_param_uuid             bobject_add_param_uuid
+#define dev_add_param_guid             bobject_add_param_guid
 #define dev_param_set_generic          bobject_param_set_generic
 
 #define dev_add_param_int              bobject_add_param_int
diff --git a/lib/parameter.c b/lib/parameter.c
index 1243a12e8701..5c8b86d0dff3 100644
--- a/lib/parameter.c
+++ b/lib/parameter.c
@@ -42,6 +42,8 @@ static const char *param_type_string[] = {
        [PARAM_TYPE_IPV4] = "ipv4",
        [PARAM_TYPE_MAC] = "MAC",
        [PARAM_TYPE_FILE_LIST] = "file-list",
+       [PARAM_TYPE_UUID] = "uuid",
+       [PARAM_TYPE_GUID] = "guid",
 };
 
 const char *get_param_type(struct param_d *param)
@@ -1095,6 +1097,99 @@ struct param_d *bobject_add_param_file_list(bobject_t 
_bobj, const char *name,
        return &pfl->param;
 }
 
+struct param_uuid {
+       struct param_d param;
+       void *uuid;
+       char *uuid_str;
+       int (*set)(struct param_d *p, void *priv);
+       int (*get)(struct param_d *p, void *priv);
+};
+
+static inline struct param_uuid *to_param_uuid(struct param_d *p)
+{
+       return container_of(p, struct param_uuid, param);
+}
+
+static int param_uuid_set(struct bobject *bobj, struct param_d *p,
+                         const char *val)
+{
+       struct param_uuid *pui = to_param_uuid(p);
+       u8 uuid_save[UUID_SIZE];
+       int ret;
+
+       if (!val || strlen(val) == UUID_STRING_LEN)
+               return -EINVAL;
+
+       memcpy(uuid_save, pui->uuid, UUID_SIZE);
+
+       if (pui->param.type == PARAM_TYPE_GUID)
+               ret = guid_parse(val, pui->uuid);
+       else
+               ret = uuid_parse(val, pui->uuid);
+
+       if (ret)
+               return ret;
+
+       if (!pui->set)
+               return 0;
+
+       ret = pui->set(p, p->driver_priv);
+       if (ret)
+               memcpy(pui->uuid, uuid_save, UUID_SIZE);
+
+       return ret;
+}
+
+static const char *param_uuid_get(struct bobject *bobj, struct param_d *p)
+{
+       struct param_uuid *pui = to_param_uuid(p);
+       int ret;
+
+       if (pui->get) {
+               ret = pui->get(p, p->driver_priv);
+               if (ret)
+                       return NULL;
+       }
+
+       p->value = xrealloc(p->value, UUID_STRING_LEN + 1);
+
+       /* We don't use xasprintf here to avoid forcing a PRINTF_UUID
+        * dependency on all CONFIG_PARAMETER users
+        */
+       *uuid_string(p->value, p->value + UUID_STRING_LEN + 1,
+                   pui->uuid, -1, -1, 0,
+                   pui->param.type == PARAM_TYPE_GUID ? "Ul" : "Ub") = '\0';
+
+       return p->value;
+}
+
+struct param_d *__bobject_add_param_uuid(bobject_t _bobj, const char *name,
+                                        int (*set)(struct param_d *p, void 
*priv),
+                                        int (*get)(struct param_d *p, void 
*priv),
+                                        void *uuid, bool is_guid,
+                                        void *priv)
+{
+       struct bobject *bobj = _bobj.bobj;
+       struct param_uuid *pui;
+       int ret;
+
+       pui = xzalloc(sizeof(*pui));
+       pui->uuid = uuid;
+       pui->set = set;
+       pui->get = get;
+       pui->param.driver_priv = priv;
+       pui->param.type = is_guid ? PARAM_TYPE_GUID : PARAM_TYPE_UUID;
+
+       ret = __bobject_add_param(&pui->param, bobj, name,
+                       param_uuid_set, param_uuid_get, 0);
+       if (ret) {
+               free(pui);
+               return ERR_PTR(ret);
+       }
+
+       return &pui->param;
+}
+
 
 /**
  * param_remove - remove a parameter and free its memory
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 6c9dae467496..2dca20b8b0a3 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -321,7 +321,7 @@ char *error_string(char *buf, const char *end, const void 
*errptr, int field_wid
     return string(buf, end, strerror(-PTR_ERR(errptr)), field_width, 
precision, flags);
 }
 
-static noinline_for_stack
+noinline_for_stack
 char *uuid_string(char *buf, const char *end, const u8 *addr, int field_width,
                  int precision, int flags, const char *fmt)
 {
-- 
2.47.3


Reply via email to