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
