Re: [ipxe-devel] [PATCH ipxe v2 3/4] [uuid] parse uuid
On 20/01/17 18:29, David Decotigny wrote: src/core/settings.c | 28 ++ src/core/uuid.c | 60 +++ src/include/ipxe/uuid.h | 1 + src/tests/settings_test.c | 4 This would add a reasonable amount of extra code to the standard ROM builds, which I don't think can easily be justified by the benefit. You can work around the absence of parse_uuid_setting() by setting uuid:hexraw, e.g. set uuid:hexraw 1a6a749d0eda461aa87a7cfe4fca4a57 One possible option would be to allow hex_decode() to treat the separator character as optional, and then treat :uuid as a variation on :hexhyp for parsing purposes. Another potential problem is that there is no universal agreement on the endianness of UUIDs. I suspect that the use of :hexraw might be the cleanest overall solution. Thanks, Michael ___ ipxe-devel mailing list ipxe-devel@lists.ipxe.org https://lists.ipxe.org/mailman/listinfo.cgi/ipxe-devel
[ipxe-devel] [PATCH ipxe v2 3/4] [uuid] parse uuid
Tested: valgrind ./tap.linux --settings uuid=$(uuidgen) ... --- src/core/settings.c | 28 ++ src/core/uuid.c | 60 +++ src/include/ipxe/uuid.h | 1 + src/tests/settings_test.c | 4 4 files changed, 93 insertions(+) diff --git a/src/core/settings.c b/src/core/settings.c index b4ccedf..5db73b8 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -2200,6 +2200,33 @@ const struct setting_type setting_type_base64 __setting_type = { }; /** + * Parse UUID setting value (canonical form) + * + * @v type Setting type + * @v valueFormatted setting value + * @v buf Buffer to contain raw value + * @v len Length of buffer + * @ret lenLength of raw value, or negative error + */ +static int parse_uuid_setting ( const struct setting_type *type __unused, +const char *value, void *buf, size_t len ) +{ + union uuid * result = ( union uuid * ) buf; + + if ( !len && !buf ) { + return sizeof( *result ); + } else if ( len != sizeof( *result ) ) { + return -EINVAL; + } + + if ( uuid_aton(result, value) ) { + return -EINVAL; + } + + return len; +} + +/** * Format UUID setting value * * @v type Setting type @@ -2225,6 +2252,7 @@ static int format_uuid_setting ( const struct setting_type *type __unused, /** UUID setting type */ const struct setting_type setting_type_uuid __setting_type = { .name = "uuid", + .parse = parse_uuid_setting, .format = format_uuid_setting, }; diff --git a/src/core/uuid.c b/src/core/uuid.c index c43d421..1c0f2a5 100644 --- a/src/core/uuid.c +++ b/src/core/uuid.c @@ -53,3 +53,63 @@ const char * uuid_ntoa ( const union uuid *uuid ) { uuid->canonical.e[4], uuid->canonical.e[5] ); return buf; } + + +/** + * Parse UUID from formatted string + * + * @v suuidUUID in canonical form (expecting the trailing \0) + * @ret string UUID + */ +int uuid_aton ( union uuid * uuid, const char * s ) { + static const char pattern[] = "----"; + uint8_t s_idx, nibble_idx; + + if ( !s || !uuid ) { + return -1; + } + + for ( s_idx = nibble_idx = 0 ; + *s && ( s_idx < ( sizeof(pattern) - 1 ) ) ; + ++s, ++s_idx ) { + uint8_t * uuid_byte = & uuid->raw[ nibble_idx >> 1 ]; + + if ( pattern[s_idx] != '0' ) { + /* we were expecting a separator */ + if ( *s != pattern[s_idx] ) { + return -1; + } + + /* skip to next input char */ + continue; + } + + /* code below is assuming clean roll-over with the +* shift operator, ie. for any initial value of uint8_t x, +* { x <<= 4 ; x <<= 4 } leads to x == 0 +*/ + ( *uuid_byte ) <<= 4; + if ( ( *s >= '0' ) && ( *s <= '9' ) ) { + ( *uuid_byte ) |= ( *s - '0' ); + } else if ( ( *s >= 'a' ) && ( *s <= 'f' ) ) { + ( *uuid_byte ) |= ( 0xa + ( *s - 'a' ) ); + } else if ( ( *s >= 'A' ) && ( *s <= 'F' ) ) { + ( *uuid_byte ) |= ( 0xa + ( *s - 'A' ) ); + } else { + return -1; + } + nibble_idx ++; + } + + if ( *s ) { + /* chars remaining after UUID string */ + return -1; + } + + if ( s_idx != ( sizeof( pattern ) - 1 ) ) { + /* UUID string was too short */ + return -1; + } + + return 0; +} diff --git a/src/include/ipxe/uuid.h b/src/include/ipxe/uuid.h index 24c46ac..75f9b78 100644 --- a/src/include/ipxe/uuid.h +++ b/src/include/ipxe/uuid.h @@ -48,5 +48,6 @@ static inline void uuid_mangle ( union uuid *uuid ) { } extern const char * uuid_ntoa ( const union uuid *uuid ); +extern int uuid_aton ( union uuid * uuid, const char * s ); #endif /* _IPXE_UUID_H */ diff --git a/src/tests/settings_test.c b/src/tests/settings_test.c index 828901b..fab8a15 100644 --- a/src/tests/settings_test.c +++ b/src/tests/settings_test.c @@ -415,6 +415,10 @@ static void settings_test_exec ( void ) { "gIGCg4QA/w==" ); /* "uuid" setting type (no store capability) */ + storef_ok ( &test_settings, &test_uuid_setting, + "1a6a749d-0eda-461a-a87a-7cfe4fca4a57", + RAW ( 0x1a, 0x6a, 0x74, 0x9d, 0x0e, 0xda, 0x46, 0x1a,0xa8, + 0x7a, 0x7c, 0xfe, 0x4f, 0xca, 0x4a, 0x57 ) ); fetchf_ok ( &test_settings, &test_uuid_setting, RAW ( 0x1a, 0x6a, 0x74, 0x9d,
[ipxe-devel] [PATCH ipxe v2 3/4] [uuid] parse uuid
Tested: valgrind ./tap.linux --settings uuid=$(uuidgen) ... --- src/core/settings.c | 28 ++ src/core/uuid.c | 60 +++ src/include/ipxe/uuid.h | 1 + src/tests/settings_test.c | 4 4 files changed, 93 insertions(+) diff --git a/src/core/settings.c b/src/core/settings.c index b4ccedf..5db73b8 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -2200,6 +2200,33 @@ const struct setting_type setting_type_base64 __setting_type = { }; /** + * Parse UUID setting value (canonical form) + * + * @v type Setting type + * @v valueFormatted setting value + * @v buf Buffer to contain raw value + * @v len Length of buffer + * @ret lenLength of raw value, or negative error + */ +static int parse_uuid_setting ( const struct setting_type *type __unused, +const char *value, void *buf, size_t len ) +{ + union uuid * result = ( union uuid * ) buf; + + if ( !len && !buf ) { + return sizeof( *result ); + } else if ( len != sizeof( *result ) ) { + return -EINVAL; + } + + if ( uuid_aton(result, value) ) { + return -EINVAL; + } + + return len; +} + +/** * Format UUID setting value * * @v type Setting type @@ -2225,6 +2252,7 @@ static int format_uuid_setting ( const struct setting_type *type __unused, /** UUID setting type */ const struct setting_type setting_type_uuid __setting_type = { .name = "uuid", + .parse = parse_uuid_setting, .format = format_uuid_setting, }; diff --git a/src/core/uuid.c b/src/core/uuid.c index c43d421..1c0f2a5 100644 --- a/src/core/uuid.c +++ b/src/core/uuid.c @@ -53,3 +53,63 @@ const char * uuid_ntoa ( const union uuid *uuid ) { uuid->canonical.e[4], uuid->canonical.e[5] ); return buf; } + + +/** + * Parse UUID from formatted string + * + * @v suuidUUID in canonical form (expecting the trailing \0) + * @ret string UUID + */ +int uuid_aton ( union uuid * uuid, const char * s ) { + static const char pattern[] = "----"; + uint8_t s_idx, nibble_idx; + + if ( !s || !uuid ) { + return -1; + } + + for ( s_idx = nibble_idx = 0 ; + *s && ( s_idx < ( sizeof(pattern) - 1 ) ) ; + ++s, ++s_idx ) { + uint8_t * uuid_byte = & uuid->raw[ nibble_idx >> 1 ]; + + if ( pattern[s_idx] != '0' ) { + /* we were expecting a separator */ + if ( *s != pattern[s_idx] ) { + return -1; + } + + /* skip to next input char */ + continue; + } + + /* code below is assuming clean roll-over with the +* shift operator, ie. for any initial value of uint8_t x, +* { x <<= 4 ; x <<= 4 } leads to x == 0 +*/ + ( *uuid_byte ) <<= 4; + if ( ( *s >= '0' ) && ( *s <= '9' ) ) { + ( *uuid_byte ) |= ( *s - '0' ); + } else if ( ( *s >= 'a' ) && ( *s <= 'f' ) ) { + ( *uuid_byte ) |= ( 0xa + ( *s - 'a' ) ); + } else if ( ( *s >= 'A' ) && ( *s <= 'F' ) ) { + ( *uuid_byte ) |= ( 0xa + ( *s - 'A' ) ); + } else { + return -1; + } + nibble_idx ++; + } + + if ( *s ) { + /* chars remaining after UUID string */ + return -1; + } + + if ( s_idx != ( sizeof( pattern ) - 1 ) ) { + /* UUID string was too short */ + return -1; + } + + return 0; +} diff --git a/src/include/ipxe/uuid.h b/src/include/ipxe/uuid.h index 24c46ac..75f9b78 100644 --- a/src/include/ipxe/uuid.h +++ b/src/include/ipxe/uuid.h @@ -48,5 +48,6 @@ static inline void uuid_mangle ( union uuid *uuid ) { } extern const char * uuid_ntoa ( const union uuid *uuid ); +extern int uuid_aton ( union uuid * uuid, const char * s ); #endif /* _IPXE_UUID_H */ diff --git a/src/tests/settings_test.c b/src/tests/settings_test.c index 828901b..fab8a15 100644 --- a/src/tests/settings_test.c +++ b/src/tests/settings_test.c @@ -415,6 +415,10 @@ static void settings_test_exec ( void ) { "gIGCg4QA/w==" ); /* "uuid" setting type (no store capability) */ + storef_ok ( &test_settings, &test_uuid_setting, + "1a6a749d-0eda-461a-a87a-7cfe4fca4a57", + RAW ( 0x1a, 0x6a, 0x74, 0x9d, 0x0e, 0xda, 0x46, 0x1a,0xa8, + 0x7a, 0x7c, 0xfe, 0x4f, 0xca, 0x4a, 0x57 ) ); fetchf_ok ( &test_settings, &test_uuid_setting, RAW ( 0x1a, 0x6a, 0x74, 0x9d,
[ipxe-devel] [PATCH ipxe v2 3/4] [uuid] parse uuid
Tested: valgrind ./tap.linux --settings uuid=$(uuidgen) ... --- src/core/settings.c | 28 ++ src/core/uuid.c | 60 +++ src/include/ipxe/uuid.h | 1 + src/tests/settings_test.c | 4 4 files changed, 93 insertions(+) diff --git a/src/core/settings.c b/src/core/settings.c index b4ccedf..5db73b8 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -2200,6 +2200,33 @@ const struct setting_type setting_type_base64 __setting_type = { }; /** + * Parse UUID setting value (canonical form) + * + * @v type Setting type + * @v valueFormatted setting value + * @v buf Buffer to contain raw value + * @v len Length of buffer + * @ret lenLength of raw value, or negative error + */ +static int parse_uuid_setting ( const struct setting_type *type __unused, +const char *value, void *buf, size_t len ) +{ + union uuid * result = ( union uuid * ) buf; + + if ( !len && !buf ) { + return sizeof( *result ); + } else if ( len != sizeof( *result ) ) { + return -EINVAL; + } + + if ( uuid_aton(result, value) ) { + return -EINVAL; + } + + return len; +} + +/** * Format UUID setting value * * @v type Setting type @@ -2225,6 +2252,7 @@ static int format_uuid_setting ( const struct setting_type *type __unused, /** UUID setting type */ const struct setting_type setting_type_uuid __setting_type = { .name = "uuid", + .parse = parse_uuid_setting, .format = format_uuid_setting, }; diff --git a/src/core/uuid.c b/src/core/uuid.c index c43d421..1c0f2a5 100644 --- a/src/core/uuid.c +++ b/src/core/uuid.c @@ -53,3 +53,63 @@ const char * uuid_ntoa ( const union uuid *uuid ) { uuid->canonical.e[4], uuid->canonical.e[5] ); return buf; } + + +/** + * Parse UUID from formatted string + * + * @v suuidUUID in canonical form (expecting the trailing \0) + * @ret string UUID + */ +int uuid_aton ( union uuid * uuid, const char * s ) { + static const char pattern[] = "----"; + uint8_t s_idx, nibble_idx; + + if ( !s || !uuid ) { + return -1; + } + + for ( s_idx = nibble_idx = 0 ; + *s && ( s_idx < ( sizeof(pattern) - 1 ) ) ; + ++s, ++s_idx ) { + uint8_t * uuid_byte = & uuid->raw[ nibble_idx >> 1 ]; + + if ( pattern[s_idx] != '0' ) { + /* we were expecting a separator */ + if ( *s != pattern[s_idx] ) { + return -1; + } + + /* skip to next input char */ + continue; + } + + /* code below is assuming clean roll-over with the +* shift operator, ie. for any initial value of uint8_t x, +* { x <<= 4 ; x <<= 4 } leads to x == 0 +*/ + ( *uuid_byte ) <<= 4; + if ( ( *s >= '0' ) && ( *s <= '9' ) ) { + ( *uuid_byte ) |= ( *s - '0' ); + } else if ( ( *s >= 'a' ) && ( *s <= 'f' ) ) { + ( *uuid_byte ) |= ( 0xa + ( *s - 'a' ) ); + } else if ( ( *s >= 'A' ) && ( *s <= 'F' ) ) { + ( *uuid_byte ) |= ( 0xa + ( *s - 'A' ) ); + } else { + return -1; + } + nibble_idx ++; + } + + if ( *s ) { + /* chars remaining after UUID string */ + return -1; + } + + if ( s_idx != ( sizeof( pattern ) - 1 ) ) { + /* UUID string was too short */ + return -1; + } + + return 0; +} diff --git a/src/include/ipxe/uuid.h b/src/include/ipxe/uuid.h index 24c46ac..75f9b78 100644 --- a/src/include/ipxe/uuid.h +++ b/src/include/ipxe/uuid.h @@ -48,5 +48,6 @@ static inline void uuid_mangle ( union uuid *uuid ) { } extern const char * uuid_ntoa ( const union uuid *uuid ); +extern int uuid_aton ( union uuid * uuid, const char * s ); #endif /* _IPXE_UUID_H */ diff --git a/src/tests/settings_test.c b/src/tests/settings_test.c index 828901b..fab8a15 100644 --- a/src/tests/settings_test.c +++ b/src/tests/settings_test.c @@ -415,6 +415,10 @@ static void settings_test_exec ( void ) { "gIGCg4QA/w==" ); /* "uuid" setting type (no store capability) */ + storef_ok ( &test_settings, &test_uuid_setting, + "1a6a749d-0eda-461a-a87a-7cfe4fca4a57", + RAW ( 0x1a, 0x6a, 0x74, 0x9d, 0x0e, 0xda, 0x46, 0x1a,0xa8, + 0x7a, 0x7c, 0xfe, 0x4f, 0xca, 0x4a, 0x57 ) ); fetchf_ok ( &test_settings, &test_uuid_setting, RAW ( 0x1a, 0x6a, 0x74, 0x9d,
[ipxe-devel] [PATCH ipxe v2 3/4] [uuid] parse uuid
Tested: valgrind ./tap.linux --settings uuid=$(uuidgen) ... --- src/core/settings.c | 28 ++ src/core/uuid.c | 60 +++ src/include/ipxe/uuid.h | 1 + src/tests/settings_test.c | 4 4 files changed, 93 insertions(+) diff --git a/src/core/settings.c b/src/core/settings.c index b4ccedf..5db73b8 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -2200,6 +2200,33 @@ const struct setting_type setting_type_base64 __setting_type = { }; /** + * Parse UUID setting value (canonical form) + * + * @v type Setting type + * @v valueFormatted setting value + * @v buf Buffer to contain raw value + * @v len Length of buffer + * @ret lenLength of raw value, or negative error + */ +static int parse_uuid_setting ( const struct setting_type *type __unused, +const char *value, void *buf, size_t len ) +{ + union uuid * result = ( union uuid * ) buf; + + if ( !len && !buf ) { + return sizeof( *result ); + } else if ( len != sizeof( *result ) ) { + return -EINVAL; + } + + if ( uuid_aton(result, value) ) { + return -EINVAL; + } + + return len; +} + +/** * Format UUID setting value * * @v type Setting type @@ -2225,6 +2252,7 @@ static int format_uuid_setting ( const struct setting_type *type __unused, /** UUID setting type */ const struct setting_type setting_type_uuid __setting_type = { .name = "uuid", + .parse = parse_uuid_setting, .format = format_uuid_setting, }; diff --git a/src/core/uuid.c b/src/core/uuid.c index c43d421..1c0f2a5 100644 --- a/src/core/uuid.c +++ b/src/core/uuid.c @@ -53,3 +53,63 @@ const char * uuid_ntoa ( const union uuid *uuid ) { uuid->canonical.e[4], uuid->canonical.e[5] ); return buf; } + + +/** + * Parse UUID from formatted string + * + * @v suuidUUID in canonical form (expecting the trailing \0) + * @ret string UUID + */ +int uuid_aton ( union uuid * uuid, const char * s ) { + static const char pattern[] = "----"; + uint8_t s_idx, nibble_idx; + + if ( !s || !uuid ) { + return -1; + } + + for ( s_idx = nibble_idx = 0 ; + *s && ( s_idx < ( sizeof(pattern) - 1 ) ) ; + ++s, ++s_idx ) { + uint8_t * uuid_byte = & uuid->raw[ nibble_idx >> 1 ]; + + if ( pattern[s_idx] != '0' ) { + /* we were expecting a separator */ + if ( *s != pattern[s_idx] ) { + return -1; + } + + /* skip to next input char */ + continue; + } + + /* code below is assuming clean roll-over with the +* shift operator, ie. for any initial value of uint8_t x, +* { x <<= 4 ; x <<= 4 } leads to x == 0 +*/ + ( *uuid_byte ) <<= 4; + if ( ( *s >= '0' ) && ( *s <= '9' ) ) { + ( *uuid_byte ) |= ( *s - '0' ); + } else if ( ( *s >= 'a' ) && ( *s <= 'f' ) ) { + ( *uuid_byte ) |= ( 0xa + ( *s - 'a' ) ); + } else if ( ( *s >= 'A' ) && ( *s <= 'F' ) ) { + ( *uuid_byte ) |= ( 0xa + ( *s - 'A' ) ); + } else { + return -1; + } + nibble_idx ++; + } + + if ( *s ) { + /* chars remaining after UUID string */ + return -1; + } + + if ( s_idx != ( sizeof( pattern ) - 1 ) ) { + /* UUID string was too short */ + return -1; + } + + return 0; +} diff --git a/src/include/ipxe/uuid.h b/src/include/ipxe/uuid.h index 24c46ac..75f9b78 100644 --- a/src/include/ipxe/uuid.h +++ b/src/include/ipxe/uuid.h @@ -48,5 +48,6 @@ static inline void uuid_mangle ( union uuid *uuid ) { } extern const char * uuid_ntoa ( const union uuid *uuid ); +extern int uuid_aton ( union uuid * uuid, const char * s ); #endif /* _IPXE_UUID_H */ diff --git a/src/tests/settings_test.c b/src/tests/settings_test.c index 828901b..fab8a15 100644 --- a/src/tests/settings_test.c +++ b/src/tests/settings_test.c @@ -415,6 +415,10 @@ static void settings_test_exec ( void ) { "gIGCg4QA/w==" ); /* "uuid" setting type (no store capability) */ + storef_ok ( &test_settings, &test_uuid_setting, + "1a6a749d-0eda-461a-a87a-7cfe4fca4a57", + RAW ( 0x1a, 0x6a, 0x74, 0x9d, 0x0e, 0xda, 0x46, 0x1a,0xa8, + 0x7a, 0x7c, 0xfe, 0x4f, 0xca, 0x4a, 0x57 ) ); fetchf_ok ( &test_settings, &test_uuid_setting, RAW ( 0x1a, 0x6a, 0x74, 0x9d,