Browse Source

[settings] Introduce the generalised concept of a numeric setting

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 11 years ago
parent
commit
c70d4cb1b3
4 changed files with 542 additions and 183 deletions
  1. 1
    1
      src/arch/i386/interface/vmware/guestinfo.c
  2. 412
    175
      src/core/settings.c
  3. 40
    5
      src/include/ipxe/settings.h
  4. 89
    2
      src/tests/settings_test.c

+ 1
- 1
src/arch/i386/interface/vmware/guestinfo.c View File

@@ -114,7 +114,7 @@ static int guestinfo_fetch_type ( struct settings *settings,
114 114
 		settings, &command[9] /* Skip "info-get " */, info );
115 115
 
116 116
 	/* Parse GuestInfo value according to type */
117
-	ret = type->parse ( info, data, len );
117
+	ret = setting_parse ( type, info, data, len );
118 118
 	if ( ret < 0 ) {
119 119
 		DBGC ( settings, "GuestInfo %p could not parse \"%s\" as %s: "
120 120
 		       "%s\n", settings, info, type->name, strerror ( ret ) );

+ 412
- 175
src/core/settings.c View File

@@ -850,15 +850,14 @@ int fetch_ipv4_setting ( struct settings *settings, struct setting *setting,
850 850
 /**
851 851
  * Extract numeric value of setting
852 852
  *
853
+ * @v is_signed		Treat value as a signed integer
853 854
  * @v raw		Raw setting data
854 855
  * @v len		Length of raw setting data
855
- * @ret signed_value	Value, when interpreted as a signed integer
856
- * @ret unsigned_value	Value, when interpreted as an unsigned integer
856
+ * @ret value		Numeric value
857 857
  * @ret len		Length of setting, or negative error
858 858
  */
859
-static int numeric_setting_value ( const void *raw, size_t len,
860
-				   signed long *signed_value,
861
-				   unsigned long *unsigned_value ) {
859
+static int numeric_setting_value ( int is_signed, const void *raw, size_t len,
860
+				   unsigned long *value ) {
862 861
 	const uint8_t *unsigned_bytes = raw;
863 862
 	const int8_t *signed_bytes = raw;
864 863
 	int is_negative;
@@ -871,29 +870,26 @@ static int numeric_setting_value ( const void *raw, size_t len,
871 870
 
872 871
 	/* Convert to host-ordered longs */
873 872
 	is_negative = ( len && ( signed_bytes[0] < 0 ) );
874
-	*signed_value = ( is_negative ? -1L : 0 );
875
-	*unsigned_value = 0;
873
+	*value = ( ( is_signed && is_negative ) ? -1L : 0 );
876 874
 	for ( i = 0 ; i < len ; i++ ) {
877 875
 		byte = unsigned_bytes[i];
878
-		*signed_value = ( ( *signed_value << 8 ) | byte );
879
-		*unsigned_value = ( ( *unsigned_value << 8 ) | byte );
876
+		*value = ( ( *value << 8 ) | byte );
880 877
 	}
881 878
 
882 879
 	return len;
883 880
 }
884 881
 
885 882
 /**
886
- * Fetch value of signed integer setting
883
+ * Fetch value of numeric setting
887 884
  *
888 885
  * @v settings		Settings block, or NULL to search all blocks
889 886
  * @v setting		Setting to fetch
890 887
  * @v value		Integer value to fill in
891 888
  * @ret len		Length of setting, or negative error
892 889
  */
893
-int fetch_int_setting ( struct settings *settings, struct setting *setting,
894
-			long *value ) {
895
-	unsigned long dummy;
896
-	long tmp;
890
+int fetch_numeric_setting ( struct settings *settings, struct setting *setting,
891
+			    unsigned long *value, int is_signed ) {
892
+	unsigned long tmp;
897 893
 	int len;
898 894
 
899 895
 	/* Avoid returning uninitialised data on error */
@@ -905,7 +901,22 @@ int fetch_int_setting ( struct settings *settings, struct setting *setting,
905 901
 		return len;
906 902
 
907 903
 	/* Extract numeric value */
908
-	return numeric_setting_value ( &tmp, len, value, &dummy );
904
+	return numeric_setting_value ( is_signed, &tmp, len, value );
905
+}
906
+
907
+/**
908
+ * Fetch value of signed integer setting
909
+ *
910
+ * @v settings		Settings block, or NULL to search all blocks
911
+ * @v setting		Setting to fetch
912
+ * @v value		Integer value to fill in
913
+ * @ret len		Length of setting, or negative error
914
+ */
915
+int fetch_int_setting ( struct settings *settings, struct setting *setting,
916
+			long *value ) {
917
+
918
+	return fetch_numeric_setting ( settings, setting,
919
+				       ( ( unsigned long * ) value ), 1 );
909 920
 }
910 921
 
911 922
 /**
@@ -918,20 +929,8 @@ int fetch_int_setting ( struct settings *settings, struct setting *setting,
918 929
  */
919 930
 int fetch_uint_setting ( struct settings *settings, struct setting *setting,
920 931
 			 unsigned long *value ) {
921
-	signed long dummy;
922
-	long tmp;
923
-	int len;
924 932
 
925
-	/* Avoid returning uninitialised data on error */
926
-	*value = 0;
927
-
928
-	/* Fetch raw (network-ordered, variable-length) setting */
929
-	len = fetch_setting ( settings, setting, &tmp, sizeof ( tmp ) );
930
-	if ( len < 0 )
931
-		return len;
932
-
933
-	/* Extract numeric value */
934
-	return numeric_setting_value ( &tmp, len, &dummy, value );
933
+	return fetch_numeric_setting ( settings, setting, value, 0 );
935 934
 }
936 935
 
937 936
 /**
@@ -942,9 +941,9 @@ int fetch_uint_setting ( struct settings *settings, struct setting *setting,
942 941
  * @ret value		Setting value, or zero
943 942
  */
944 943
 long fetch_intz_setting ( struct settings *settings, struct setting *setting ){
945
-	long value;
944
+	unsigned long value;
946 945
 
947
-	fetch_int_setting ( settings, setting, &value );
946
+	fetch_numeric_setting ( settings, setting, &value, 1 );
948 947
 	return value;
949 948
 }
950 949
 
@@ -959,7 +958,7 @@ unsigned long fetch_uintz_setting ( struct settings *settings,
959 958
 				    struct setting *setting ) {
960 959
 	unsigned long value;
961 960
 
962
-	fetch_uint_setting ( settings, setting, &value );
961
+	fetch_numeric_setting ( settings, setting, &value, 0 );
963 962
 	return value;
964 963
 }
965 964
 
@@ -1027,12 +1026,88 @@ int setting_cmp ( struct setting *a, struct setting *b ) {
1027 1026
  ******************************************************************************
1028 1027
  */
1029 1028
 
1029
+/**
1030
+ * Format setting value as a string
1031
+ *
1032
+ * @v type		Setting type
1033
+ * @v raw		Raw setting value
1034
+ * @v raw_len		Length of raw setting value
1035
+ * @v buf		Buffer to contain formatted value
1036
+ * @v len		Length of buffer
1037
+ * @ret len		Length of formatted value, or negative error
1038
+ */
1039
+int setting_format ( struct setting_type *type, const void *raw,
1040
+		     size_t raw_len, char *buf, size_t len ) {
1041
+
1042
+	/* Sanity check */
1043
+	if ( ! type->format )
1044
+		return -ENOTSUP;
1045
+
1046
+	return type->format ( type, raw, raw_len, buf, len );
1047
+}
1048
+
1049
+/**
1050
+ * Parse formatted string to setting value
1051
+ *
1052
+ * @v type		Setting type
1053
+ * @v value		Formatted setting value
1054
+ * @v buf		Buffer to contain raw value
1055
+ * @v len		Length of buffer
1056
+ * @ret len		Length of raw value, or negative error
1057
+ */
1058
+int setting_parse ( struct setting_type *type, const char *value,
1059
+		    void *buf, size_t len ) {
1060
+
1061
+	/* Sanity check */
1062
+	if ( ! type->parse )
1063
+		return -ENOTSUP;
1064
+
1065
+	return type->parse ( type, value, buf, len );
1066
+}
1067
+
1068
+/**
1069
+ * Convert setting value to number
1070
+ *
1071
+ * @v type		Setting type
1072
+ * @v raw		Raw setting value
1073
+ * @v raw_len		Length of raw setting value
1074
+ * @ret value		Numeric value
1075
+ * @ret rc		Return status code
1076
+ */
1077
+int setting_numerate ( struct setting_type *type, const void *raw,
1078
+		       size_t raw_len, unsigned long *value ) {
1079
+
1080
+	/* Sanity check */
1081
+	if ( ! type->numerate )
1082
+		return -ENOTSUP;
1083
+
1084
+	return type->numerate ( type, raw, raw_len, value );
1085
+}
1086
+
1087
+/**
1088
+ * Convert number to setting value
1089
+ *
1090
+ * @v type		Setting type
1091
+ * @v value		Numeric value
1092
+ * @v buf		Buffer to contain raw value
1093
+ * @v len		Length of buffer
1094
+ * @ret len		Length of raw value, or negative error
1095
+ */
1096
+int setting_denumerate ( struct setting_type *type, unsigned long value,
1097
+			 void *buf, size_t len ) {
1098
+
1099
+	/* Sanity check */
1100
+	if ( ! type->denumerate )
1101
+		return -ENOTSUP;
1102
+
1103
+	return type->denumerate ( type, value, buf, len );
1104
+}
1105
+
1030 1106
 /**
1031 1107
  * Fetch formatted value of setting
1032 1108
  *
1033 1109
  * @v settings		Settings block, or NULL to search all blocks
1034 1110
  * @v setting		Setting to fetch
1035
- * @v type		Settings type
1036 1111
  * @v buf		Buffer to contain formatted value
1037 1112
  * @v len		Length of buffer
1038 1113
  * @ret len		Length of formatted value, or negative error
@@ -1052,10 +1127,10 @@ int fetchf_setting ( struct settings *settings, struct setting *setting,
1052 1127
 
1053 1128
 	/* Sanity check */
1054 1129
 	assert ( setting->type != NULL );
1055
-	assert ( setting->type->format != NULL );
1056 1130
 
1057 1131
 	/* Format setting */
1058
-	if ( ( ret = setting->type->format ( raw, raw_len, buf, len ) ) < 0 )
1132
+	if ( ( ret = setting_format ( setting->type, raw, raw_len, buf,
1133
+				      len ) ) < 0 )
1059 1134
 		goto err_format;
1060 1135
 
1061 1136
  err_format:
@@ -1069,7 +1144,6 @@ int fetchf_setting ( struct settings *settings, struct setting *setting,
1069 1144
  *
1070 1145
  * @v settings		Settings block, or NULL to search all blocks
1071 1146
  * @v setting		Setting to fetch
1072
- * @v type		Settings type
1073 1147
  * @v value		Buffer to allocate and fill with formatted value
1074 1148
  * @ret len		Length of formatted value, or negative error
1075 1149
  *
@@ -1122,13 +1196,12 @@ int storef_setting ( struct settings *settings, struct setting *setting,
1122 1196
 
1123 1197
 	/* Sanity check */
1124 1198
 	assert ( setting->type != NULL );
1125
-	assert ( setting->type->parse != NULL );
1126 1199
 
1127 1200
 	/* Get raw value length */
1128
-	raw_len = setting->type->parse ( value, NULL, 0 );
1201
+	raw_len = setting_parse ( setting->type, value, NULL, 0 );
1129 1202
 	if ( raw_len < 0 ) {
1130 1203
 		rc = raw_len;
1131
-		goto err_parse_len;
1204
+		goto err_raw_len;
1132 1205
 	}
1133 1206
 
1134 1207
 	/* Allocate buffer for raw value */
@@ -1139,7 +1212,89 @@ int storef_setting ( struct settings *settings, struct setting *setting,
1139 1212
 	}
1140 1213
 
1141 1214
 	/* Parse formatted value */
1142
-	check_len = setting->type->parse ( value, raw, raw_len );
1215
+	check_len = setting_parse ( setting->type, value, raw, raw_len );
1216
+	assert ( check_len == raw_len );
1217
+
1218
+	/* Store raw value */
1219
+	if ( ( rc = store_setting ( settings, setting, raw, raw_len ) ) != 0 )
1220
+		goto err_store;
1221
+
1222
+ err_store:
1223
+	free ( raw );
1224
+ err_alloc_raw:
1225
+ err_raw_len:
1226
+	return rc;
1227
+}
1228
+
1229
+/**
1230
+ * Fetch numeric value of setting
1231
+ *
1232
+ * @v settings		Settings block, or NULL to search all blocks
1233
+ * @v setting		Setting to fetch
1234
+ * @v value		Numeric value to fill in
1235
+ * @ret rc		Return status code
1236
+ */
1237
+int fetchn_setting ( struct settings *settings, struct setting *setting,
1238
+		     unsigned long *value ) {
1239
+	void *raw;
1240
+	int raw_len;
1241
+	int rc;
1242
+
1243
+	/* Fetch raw value */
1244
+	raw_len = fetch_setting_copy ( settings, setting, &raw );
1245
+	if ( raw_len < 0 ) {
1246
+		rc = raw_len;
1247
+		goto err_fetch_copy;
1248
+	}
1249
+
1250
+	/* Sanity check */
1251
+	assert ( setting->type != NULL );
1252
+
1253
+	/* Numerate setting */
1254
+	if ( ( rc = setting_numerate ( setting->type, raw, raw_len,
1255
+				       value ) ) < 0 )
1256
+		goto err_numerate;
1257
+
1258
+ err_numerate:
1259
+	free ( raw );
1260
+ err_fetch_copy:
1261
+	return rc;
1262
+}
1263
+
1264
+/**
1265
+ * Store numeric value of setting
1266
+ *
1267
+ * @v settings		Settings block
1268
+ * @v setting		Setting
1269
+ * @v value		Numeric value
1270
+ * @ret rc		Return status code
1271
+ */
1272
+int storen_setting ( struct settings *settings, struct setting *setting,
1273
+		     unsigned long value ) {
1274
+	void *raw;
1275
+	int raw_len;
1276
+	int check_len;
1277
+	int rc;
1278
+
1279
+	/* Sanity check */
1280
+	assert ( setting->type != NULL );
1281
+
1282
+	/* Get raw value length */
1283
+	raw_len = setting_denumerate ( setting->type, value, NULL, 0 );
1284
+	if ( raw_len < 0 ) {
1285
+		rc = raw_len;
1286
+		goto err_raw_len;
1287
+	}
1288
+
1289
+	/* Allocate buffer for raw value */
1290
+	raw = malloc ( raw_len );
1291
+	if ( ! raw ) {
1292
+		rc = -ENOMEM;
1293
+		goto err_alloc_raw;
1294
+	}
1295
+
1296
+	/* Denumerate value */
1297
+	check_len = setting_denumerate ( setting->type, value, raw, raw_len );
1143 1298
 	assert ( check_len == raw_len );
1144 1299
 
1145 1300
 	/* Store raw value */
@@ -1149,7 +1304,7 @@ int storef_setting ( struct settings *settings, struct setting *setting,
1149 1304
  err_store:
1150 1305
 	free ( raw );
1151 1306
  err_alloc_raw:
1152
- err_parse_len:
1307
+ err_raw_len:
1153 1308
 	return rc;
1154 1309
 }
1155 1310
 
@@ -1326,12 +1481,14 @@ int setting_name ( struct settings *settings, struct setting *setting,
1326 1481
 /**
1327 1482
  * Parse string setting value
1328 1483
  *
1484
+ * @v type		Setting type
1329 1485
  * @v value		Formatted setting value
1330 1486
  * @v buf		Buffer to contain raw value
1331 1487
  * @v len		Length of buffer
1332 1488
  * @ret len		Length of raw value, or negative error
1333 1489
  */
1334
-static int parse_string_setting ( const char *value, void *buf, size_t len ) {
1490
+static int parse_string_setting ( struct setting_type *type __unused,
1491
+				  const char *value, void *buf, size_t len ) {
1335 1492
 	size_t raw_len = strlen ( value ); /* Exclude terminating NUL */
1336 1493
 
1337 1494
 	/* Copy string to buffer */
@@ -1345,13 +1502,15 @@ static int parse_string_setting ( const char *value, void *buf, size_t len ) {
1345 1502
 /**
1346 1503
  * Format string setting value
1347 1504
  *
1505
+ * @v type		Setting type
1348 1506
  * @v raw		Raw setting value
1349 1507
  * @v raw_len		Length of raw setting value
1350 1508
  * @v buf		Buffer to contain formatted value
1351 1509
  * @v len		Length of buffer
1352 1510
  * @ret len		Length of formatted value, or negative error
1353 1511
  */
1354
-static int format_string_setting ( const void *raw, size_t raw_len, char *buf,
1512
+static int format_string_setting ( struct setting_type *type __unused,
1513
+				   const void *raw, size_t raw_len, char *buf,
1355 1514
 				   size_t len ) {
1356 1515
 
1357 1516
 	/* Copy string to buffer, and terminate */
@@ -1373,13 +1532,14 @@ struct setting_type setting_type_string __setting_type = {
1373 1532
 /**
1374 1533
  * Parse URI-encoded string setting value
1375 1534
  *
1535
+ * @v type		Setting type
1376 1536
  * @v value		Formatted setting value
1377 1537
  * @v buf		Buffer to contain raw value
1378 1538
  * @v len		Length of buffer
1379 1539
  * @ret len		Length of raw value, or negative error
1380 1540
  */
1381
-static int parse_uristring_setting ( const char *value, void *buf,
1382
-				     size_t len ) {
1541
+static int parse_uristring_setting ( struct setting_type *type __unused,
1542
+				     const char *value, void *buf, size_t len ){
1383 1543
 	char tmp[ len + 1 /* NUL */ ];
1384 1544
 	size_t raw_len;
1385 1545
 
@@ -1397,13 +1557,15 @@ static int parse_uristring_setting ( const char *value, void *buf,
1397 1557
 /**
1398 1558
  * Format URI-encoded string setting value
1399 1559
  *
1560
+ * @v type		Setting type
1400 1561
  * @v raw		Raw setting value
1401 1562
  * @v raw_len		Length of raw setting value
1402 1563
  * @v buf		Buffer to contain formatted value
1403 1564
  * @v len		Length of buffer
1404 1565
  * @ret len		Length of formatted value, or negative error
1405 1566
  */
1406
-static int format_uristring_setting ( const void *raw, size_t raw_len,
1567
+static int format_uristring_setting ( struct setting_type *type __unused,
1568
+				      const void *raw, size_t raw_len,
1407 1569
 				      char *buf, size_t len ) {
1408 1570
 	char tmp[ raw_len + 1 /* NUL */ ];
1409 1571
 
@@ -1425,12 +1587,14 @@ struct setting_type setting_type_uristring __setting_type = {
1425 1587
 /**
1426 1588
  * Parse IPv4 address setting value
1427 1589
  *
1590
+ * @v type		Setting type
1428 1591
  * @v value		Formatted setting value
1429 1592
  * @v buf		Buffer to contain raw value
1430 1593
  * @v len		Length of buffer
1431 1594
  * @ret len		Length of raw value, or negative error
1432 1595
  */
1433
-static int parse_ipv4_setting ( const char *value, void *buf, size_t len ) {
1596
+static int parse_ipv4_setting ( struct setting_type *type __unused,
1597
+				const char *value, void *buf, size_t len ) {
1434 1598
 	struct in_addr ipv4;
1435 1599
 
1436 1600
 	/* Parse IPv4 address */
@@ -1448,13 +1612,15 @@ static int parse_ipv4_setting ( const char *value, void *buf, size_t len ) {
1448 1612
 /**
1449 1613
  * Format IPv4 address setting value
1450 1614
  *
1615
+ * @v type		Setting type
1451 1616
  * @v raw		Raw setting value
1452 1617
  * @v raw_len		Length of raw setting value
1453 1618
  * @v buf		Buffer to contain formatted value
1454 1619
  * @v len		Length of buffer
1455 1620
  * @ret len		Length of formatted value, or negative error
1456 1621
  */
1457
-static int format_ipv4_setting ( const void *raw, size_t raw_len, char *buf,
1622
+static int format_ipv4_setting ( struct setting_type *type __unused,
1623
+				 const void *raw, size_t raw_len, char *buf,
1458 1624
 				 size_t len ) {
1459 1625
 	const struct in_addr *ipv4 = raw;
1460 1626
 
@@ -1471,28 +1637,100 @@ struct setting_type setting_type_ipv4 __setting_type = {
1471 1637
 };
1472 1638
 
1473 1639
 /**
1474
- * Parse integer setting value
1640
+ * Integer setting type indices
1475 1641
  *
1476
- * @v value		Formatted setting value
1642
+ * These indexes are defined such that (1<<index) gives the width of
1643
+ * the integer, in bytes.
1644
+ */
1645
+enum setting_type_int_index {
1646
+	SETTING_TYPE_INT8 = 0,
1647
+	SETTING_TYPE_INT16 = 1,
1648
+	SETTING_TYPE_INT32 = 2,
1649
+};
1650
+
1651
+/**
1652
+ * Integer setting type names
1653
+ *
1654
+ * These names exist as a static array in order to allow the type's
1655
+ * integer size and signedness to be determined from the type's name.
1656
+ * Note that there are no separate entries for the signed integer
1657
+ * types: the name pointers simply point to the second character of
1658
+ * the relevant string.
1659
+ */
1660
+static const char setting_type_int_name[][8] = {
1661
+	[SETTING_TYPE_INT8] = "uint8",
1662
+	[SETTING_TYPE_INT16] = "uint16",
1663
+	[SETTING_TYPE_INT32] = "uint32",
1664
+};
1665
+
1666
+/**
1667
+ * Get unsigned integer setting type name
1668
+ *
1669
+ * @v index		Integer setting type index
1670
+ * @ret name		Setting type name
1671
+ */
1672
+#define SETTING_TYPE_UINT_NAME( index ) setting_type_int_name[index]
1673
+
1674
+/**
1675
+ * Get signed integer setting type name
1676
+ *
1677
+ * @v index		Integer setting type index
1678
+ * @ret name		Setting type name
1679
+ */
1680
+#define SETTING_TYPE_INT_NAME( index ) ( setting_type_int_name[index] + 1 )
1681
+
1682
+/**
1683
+ * Get integer setting type index
1684
+ *
1685
+ * @v type		Setting type
1686
+ * @ret index		Integer setting type index
1687
+ */
1688
+static unsigned int setting_type_int_index ( struct setting_type *type ) {
1689
+
1690
+	return ( ( type->name - setting_type_int_name[0] ) /
1691
+		 sizeof ( setting_type_int_name[0] ) );
1692
+}
1693
+
1694
+/**
1695
+ * Get integer setting type width
1696
+ *
1697
+ * @v type		Setting type
1698
+ * @ret index		Integer setting type width
1699
+ */
1700
+static unsigned int setting_type_int_width ( struct setting_type *type ) {
1701
+
1702
+	return ( 1 << setting_type_int_index ( type ) );
1703
+}
1704
+
1705
+/**
1706
+ * Get integer setting type signedness
1707
+ *
1708
+ * @v type		Setting type
1709
+ * @ret is_signed	Integer setting type is signed
1710
+ */
1711
+static int setting_type_int_is_signed ( struct setting_type *type ) {
1712
+	return ( ( type->name - setting_type_int_name[0] ) & 1 );
1713
+}
1714
+
1715
+/**
1716
+ * Convert number to setting value
1717
+ *
1718
+ * @v type		Setting type
1719
+ * @v value		Numeric value
1477 1720
  * @v buf		Buffer to contain raw value
1478 1721
  * @v len		Length of buffer
1479
- * @v size		Integer size, in bytes
1480 1722
  * @ret len		Length of raw value, or negative error
1481 1723
  */
1482
-static int parse_int_setting ( const char *value, void *buf, size_t len,
1483
-			       unsigned int size ) {
1724
+static int denumerate_int_setting ( struct setting_type *type,
1725
+				    unsigned long value, void *buf,
1726
+				    size_t len ) {
1727
+	unsigned int size = setting_type_int_width ( type );
1484 1728
 	union {
1485 1729
 		uint32_t num;
1486 1730
 		uint8_t bytes[4];
1487 1731
 	} u;
1488
-	char *endp;
1489
-
1490
-	/* Parse value */
1491
-	u.num = htonl ( strtoul ( value, &endp, 0 ) );
1492
-	if ( *endp )
1493
-		return -EINVAL;
1494 1732
 
1495
-	/* Copy to buffer */
1733
+	u.num = htonl ( value );
1496 1734
 	if ( len > size )
1497 1735
 		len = size;
1498 1736
 	memcpy ( buf, &u.bytes[ sizeof ( u ) - size ], len );
@@ -1501,64 +1739,69 @@ static int parse_int_setting ( const char *value, void *buf, size_t len,
1501 1739
 }
1502 1740
 
1503 1741
 /**
1504
- * Parse 8-bit integer setting value
1742
+ * Convert setting value to number
1505 1743
  *
1506
- * @v value		Formatted setting value
1507
- * @v buf		Buffer to contain raw value
1508
- * @v len		Length of buffer
1509
- * @v size		Integer size, in bytes
1510
- * @ret len		Length of raw value, or negative error
1744
+ * @v type		Setting type
1745
+ * @v raw		Raw setting value
1746
+ * @v raw_len		Length of raw setting value
1747
+ * @v value		Numeric value to fill in
1748
+ * @ret rc		Return status code
1511 1749
  */
1512
-static int parse_int8_setting ( const char *value, void *buf, size_t len ) {
1513
-	return parse_int_setting ( value, buf, len, sizeof ( uint8_t ) );
1514
-}
1750
+static int numerate_int_setting ( struct setting_type *type,
1751
+				  const void *raw, size_t raw_len,
1752
+				  unsigned long *value ) {
1753
+	int is_signed = setting_type_int_is_signed ( type );
1754
+	int check_len;
1515 1755
 
1516
-/**
1517
- * Parse 16-bit integer setting value
1518
- *
1519
- * @v value		Formatted setting value
1520
- * @v buf		Buffer to contain raw value
1521
- * @v len		Length of buffer
1522
- * @v size		Integer size, in bytes
1523
- * @ret len		Length of raw value, or negative error
1524
- */
1525
-static int parse_int16_setting ( const char *value, void *buf, size_t len ) {
1526
-	return parse_int_setting ( value, buf, len, sizeof ( uint16_t ) );
1756
+	/* Extract numeric value */
1757
+	check_len = numeric_setting_value ( is_signed, raw, raw_len, value );
1758
+	if ( check_len < 0 )
1759
+		return check_len;
1760
+	assert ( check_len == ( int ) raw_len );
1761
+
1762
+	return 0;
1527 1763
 }
1528 1764
 
1529 1765
 /**
1530
- * Parse 32-bit integer setting value
1766
+ * Parse integer setting value
1531 1767
  *
1768
+ * @v type		Setting type
1532 1769
  * @v value		Formatted setting value
1533 1770
  * @v buf		Buffer to contain raw value
1534 1771
  * @v len		Length of buffer
1535
- * @v size		Integer size, in bytes
1536 1772
  * @ret len		Length of raw value, or negative error
1537 1773
  */
1538
-static int parse_int32_setting ( const char *value, void *buf, size_t len ) {
1539
-	return parse_int_setting ( value, buf, len, sizeof ( uint32_t ) );
1774
+static int parse_int_setting ( struct setting_type *type, const char *value,
1775
+			       void *buf, size_t len ) {
1776
+	char *endp;
1777
+	unsigned long num_value;
1778
+
1779
+	/* Parse value */
1780
+	num_value = strtoul ( value, &endp, 0 );
1781
+	if ( *endp )
1782
+		return -EINVAL;
1783
+
1784
+	return type->denumerate ( type, num_value, buf, len );
1540 1785
 }
1541 1786
 
1542 1787
 /**
1543 1788
  * Format signed integer setting value
1544 1789
  *
1790
+ * @v type		Setting type
1545 1791
  * @v raw		Raw setting value
1546 1792
  * @v raw_len		Length of raw setting value
1547 1793
  * @v buf		Buffer to contain formatted value
1548 1794
  * @v len		Length of buffer
1549 1795
  * @ret len		Length of formatted value, or negative error
1550 1796
  */
1551
-static int format_int_setting ( const void *raw, size_t raw_len, char *buf,
1552
-				size_t len ) {
1553
-	signed long value;
1554
-	unsigned long dummy;
1555
-	int check_len;
1797
+static int format_int_setting ( struct setting_type *type, const void *raw,
1798
+				size_t raw_len, char *buf, size_t len ) {
1799
+	unsigned long value;
1800
+	int ret;
1556 1801
 
1557 1802
 	/* Extract numeric value */
1558
-	check_len = numeric_setting_value ( raw, raw_len, &value, &dummy );
1559
-	if ( check_len < 0 )
1560
-		return check_len;
1561
-	assert ( check_len == ( int ) raw_len );
1803
+	if ( ( ret = type->numerate ( type, raw, raw_len, &value ) ) < 0 )
1804
+		return ret;
1562 1805
 
1563 1806
 	/* Format value */
1564 1807
 	return snprintf ( buf, len, "%ld", value );
@@ -1567,82 +1810,90 @@ static int format_int_setting ( const void *raw, size_t raw_len, char *buf,
1567 1810
 /**
1568 1811
  * Format unsigned integer setting value
1569 1812
  *
1813
+ * @v type		Setting type
1570 1814
  * @v raw		Raw setting value
1571 1815
  * @v raw_len		Length of raw setting value
1572 1816
  * @v buf		Buffer to contain formatted value
1573 1817
  * @v len		Length of buffer
1574 1818
  * @ret len		Length of formatted value, or negative error
1575 1819
  */
1576
-static int format_uint_setting ( const void *raw, size_t raw_len, char *buf,
1577
-				 size_t len ) {
1578
-	signed long dummy;
1820
+static int format_uint_setting ( struct setting_type *type, const void *raw,
1821
+				 size_t raw_len, char *buf, size_t len ) {
1579 1822
 	unsigned long value;
1580
-	int check_len;
1823
+	int ret;
1581 1824
 
1582 1825
 	/* Extract numeric value */
1583
-	check_len = numeric_setting_value ( raw, raw_len, &dummy, &value );
1584
-	if ( check_len < 0 )
1585
-		return check_len;
1586
-	assert ( check_len == ( int ) raw_len );
1826
+	if ( ( ret = type->numerate ( type, raw, raw_len, &value ) ) < 0 )
1827
+		return ret;
1587 1828
 
1588 1829
 	/* Format value */
1589 1830
 	return snprintf ( buf, len, "%#lx", value );
1590 1831
 }
1591 1832
 
1833
+/**
1834
+ * Define a signed integer setting type
1835
+ *
1836
+ * @v index		Integer setting type index
1837
+ * @ret type		Setting type
1838
+ */
1839
+#define SETTING_TYPE_INT( index ) {				\
1840
+	.name = SETTING_TYPE_INT_NAME ( index ),		\
1841
+	.parse = parse_int_setting,				\
1842
+	.format = format_int_setting,				\
1843
+	.denumerate = denumerate_int_setting,			\
1844
+	.numerate = numerate_int_setting,			\
1845
+}
1846
+
1847
+/**
1848
+ * Define an unsigned integer setting type
1849
+ *
1850
+ * @v index		Integer setting type index
1851
+ * @ret type		Setting type
1852
+ */
1853
+#define SETTING_TYPE_UINT( index ) {				\
1854
+	.name = SETTING_TYPE_UINT_NAME ( index ),		\
1855
+	.parse = parse_int_setting,				\
1856
+	.format = format_uint_setting,				\
1857
+	.denumerate = denumerate_int_setting,			\
1858
+	.numerate = numerate_int_setting,			\
1859
+}
1860
+
1592 1861
 /** A signed 8-bit integer setting type */
1593
-struct setting_type setting_type_int8 __setting_type = {
1594
-	.name = "int8",
1595
-	.parse = parse_int8_setting,
1596
-	.format = format_int_setting,
1597
-};
1862
+struct setting_type setting_type_int8 __setting_type =
1863
+	SETTING_TYPE_INT ( SETTING_TYPE_INT8 );
1598 1864
 
1599 1865
 /** A signed 16-bit integer setting type */
1600
-struct setting_type setting_type_int16 __setting_type = {
1601
-	.name = "int16",
1602
-	.parse = parse_int16_setting,
1603
-	.format = format_int_setting,
1604
-};
1866
+struct setting_type setting_type_int16 __setting_type =
1867
+	SETTING_TYPE_INT ( SETTING_TYPE_INT16 );
1605 1868
 
1606 1869
 /** A signed 32-bit integer setting type */
1607
-struct setting_type setting_type_int32 __setting_type = {
1608
-	.name = "int32",
1609
-	.parse = parse_int32_setting,
1610
-	.format = format_int_setting,
1611
-};
1870
+struct setting_type setting_type_int32 __setting_type =
1871
+	SETTING_TYPE_INT ( SETTING_TYPE_INT32 );
1612 1872
 
1613 1873
 /** An unsigned 8-bit integer setting type */
1614
-struct setting_type setting_type_uint8 __setting_type = {
1615
-	.name = "uint8",
1616
-	.parse = parse_int8_setting,
1617
-	.format = format_uint_setting,
1618
-};
1874
+struct setting_type setting_type_uint8 __setting_type =
1875
+	SETTING_TYPE_UINT ( SETTING_TYPE_INT8 );
1619 1876
 
1620 1877
 /** An unsigned 16-bit integer setting type */
1621
-struct setting_type setting_type_uint16 __setting_type = {
1622
-	.name = "uint16",
1623
-	.parse = parse_int16_setting,
1624
-	.format = format_uint_setting,
1625
-};
1878
+struct setting_type setting_type_uint16 __setting_type =
1879
+	SETTING_TYPE_UINT ( SETTING_TYPE_INT16 );
1626 1880
 
1627 1881
 /** An unsigned 32-bit integer setting type */
1628
-struct setting_type setting_type_uint32 __setting_type = {
1629
-	.name = "uint32",
1630
-	.parse = parse_int32_setting,
1631
-	.format = format_uint_setting,
1632
-};
1882
+struct setting_type setting_type_uint32 __setting_type =
1883
+	SETTING_TYPE_UINT ( SETTING_TYPE_INT32 );
1633 1884
 
1634 1885
 /**
1635 1886
  * Format hex string setting value
1636 1887
  *
1888
+ * @v delimiter		Byte delimiter
1637 1889
  * @v raw		Raw setting value
1638 1890
  * @v raw_len		Length of raw setting value
1639 1891
  * @v buf		Buffer to contain formatted value
1640 1892
  * @v len		Length of buffer
1641
- * @v delimiter		Byte delimiter
1642 1893
  * @ret len		Length of formatted value, or negative error
1643 1894
  */
1644
-static int format_hex_setting ( const void *raw, size_t raw_len, char *buf,
1645
-				size_t len, const char *delimiter ) {
1895
+static int format_hex_setting ( const char *delimiter, const void *raw,
1896
+				size_t raw_len, char *buf, size_t len ) {
1646 1897
 	const uint8_t *bytes = raw;
1647 1898
 	int used = 0;
1648 1899
 	unsigned int i;
@@ -1660,40 +1911,46 @@ static int format_hex_setting ( const void *raw, size_t raw_len, char *buf,
1660 1911
 /**
1661 1912
  * Parse hex string setting value (using colon delimiter)
1662 1913
  *
1914
+ * @v type		Setting type
1663 1915
  * @v value		Formatted setting value
1664 1916
  * @v buf		Buffer to contain raw value
1665 1917
  * @v len		Length of buffer
1666 1918
  * @v size		Integer size, in bytes
1667 1919
  * @ret len		Length of raw value, or negative error
1668 1920
  */
1669
-static int parse_hex_setting ( const char *value, void *buf, size_t len ) {
1921
+static int parse_hex_setting ( struct setting_type *type __unused,
1922
+			       const char *value, void *buf, size_t len ) {
1670 1923
 	return hex_decode ( value, ':', buf, len );
1671 1924
 }
1672 1925
 
1673 1926
 /**
1674 1927
  * Format hex string setting value (using colon delimiter)
1675 1928
  *
1929
+ * @v type		Setting type
1676 1930
  * @v raw		Raw setting value
1677 1931
  * @v raw_len		Length of raw setting value
1678 1932
  * @v buf		Buffer to contain formatted value
1679 1933
  * @v len		Length of buffer
1680 1934
  * @ret len		Length of formatted value, or negative error
1681 1935
  */
1682
-static int format_hex_colon_setting ( const void *raw, size_t raw_len,
1936
+static int format_hex_colon_setting ( struct setting_type *type __unused,
1937
+				      const void *raw, size_t raw_len,
1683 1938
 				      char *buf, size_t len ) {
1684
-	return format_hex_setting ( raw, raw_len, buf, len, ":" );
1939
+	return format_hex_setting ( ":", raw, raw_len, buf, len );
1685 1940
 }
1686 1941
 
1687 1942
 /**
1688 1943
  * Parse hex string setting value (using hyphen delimiter)
1689 1944
  *
1945
+ * @v type		Setting type
1690 1946
  * @v value		Formatted setting value
1691 1947
  * @v buf		Buffer to contain raw value
1692 1948
  * @v len		Length of buffer
1693 1949
  * @v size		Integer size, in bytes
1694 1950
  * @ret len		Length of raw value, or negative error
1695 1951
  */
1696
-static int parse_hex_hyphen_setting ( const char *value, void *buf,
1952
+static int parse_hex_hyphen_setting ( struct setting_type *type __unused,
1953
+				      const char *value, void *buf,
1697 1954
 				      size_t len ) {
1698 1955
 	return hex_decode ( value, '-', buf, len );
1699 1956
 }
@@ -1701,43 +1958,48 @@ static int parse_hex_hyphen_setting ( const char *value, void *buf,
1701 1958
 /**
1702 1959
  * Format hex string setting value (using hyphen delimiter)
1703 1960
  *
1961
+ * @v type		Setting type
1704 1962
  * @v raw		Raw setting value
1705 1963
  * @v raw_len		Length of raw setting value
1706 1964
  * @v buf		Buffer to contain formatted value
1707 1965
  * @v len		Length of buffer
1708 1966
  * @ret len		Length of formatted value, or negative error
1709 1967
  */
1710
-static int format_hex_hyphen_setting ( const void *raw, size_t raw_len,
1968
+static int format_hex_hyphen_setting ( struct setting_type *type __unused,
1969
+				       const void *raw, size_t raw_len,
1711 1970
 				       char *buf, size_t len ) {
1712
-	return format_hex_setting ( raw, raw_len, buf, len, "-" );
1971
+	return format_hex_setting ( "-", raw, raw_len, buf, len );
1713 1972
 }
1714 1973
 
1715 1974
 /**
1716 1975
  * Parse hex string setting value (using no delimiter)
1717 1976
  *
1977
+ * @v type		Setting type
1718 1978
  * @v value		Formatted setting value
1719 1979
  * @v buf		Buffer to contain raw value
1720 1980
  * @v len		Length of buffer
1721 1981
  * @v size		Integer size, in bytes
1722 1982
  * @ret len		Length of raw value, or negative error
1723 1983
  */
1724
-static int parse_hex_raw_setting ( const char *value, void *buf,
1725
-				   size_t len ) {
1984
+static int parse_hex_raw_setting ( struct setting_type *type __unused,
1985
+				   const char *value, void *buf, size_t len ) {
1726 1986
 	return hex_decode ( value, 0, buf, len );
1727 1987
 }
1728 1988
 
1729 1989
 /**
1730 1990
  * Format hex string setting value (using no delimiter)
1731 1991
  *
1992
+ * @v type		Setting type
1732 1993
  * @v raw		Raw setting value
1733 1994
  * @v raw_len		Length of raw setting value
1734 1995
  * @v buf		Buffer to contain formatted value
1735 1996
  * @v len		Length of buffer
1736 1997
  * @ret len		Length of formatted value, or negative error
1737 1998
  */
1738
-static int format_hex_raw_setting ( const void *raw, size_t raw_len,
1999
+static int format_hex_raw_setting ( struct setting_type *type __unused,
2000
+				    const void *raw, size_t raw_len,
1739 2001
 				    char *buf, size_t len ) {
1740
-	return format_hex_setting ( raw, raw_len, buf, len, "" );
2002
+	return format_hex_setting ( "", raw, raw_len, buf, len );
1741 2003
 }
1742 2004
 
1743 2005
 /** A hex-string setting (colon-delimited) */
@@ -1761,29 +2023,18 @@ struct setting_type setting_type_hexraw __setting_type = {
1761 2023
 	.format = format_hex_raw_setting,
1762 2024
 };
1763 2025
 
1764
-/**
1765
- * Parse UUID setting value
1766
- *
1767
- * @v value		Formatted setting value
1768
- * @v buf		Buffer to contain raw value
1769
- * @v len		Length of buffer
1770
- * @ret len		Length of raw value, or negative error
1771
- */
1772
-static int parse_uuid_setting ( const char *value __unused,
1773
-				void *buf __unused, size_t len __unused ) {
1774
-	return -ENOTSUP;
1775
-}
1776
-
1777 2026
 /**
1778 2027
  * Format UUID setting value
1779 2028
  *
2029
+ * @v type		Setting type
1780 2030
  * @v raw		Raw setting value
1781 2031
  * @v raw_len		Length of raw setting value
1782 2032
  * @v buf		Buffer to contain formatted value
1783 2033
  * @v len		Length of buffer
1784 2034
  * @ret len		Length of formatted value, or negative error
1785 2035
  */
1786
-static int format_uuid_setting ( const void *raw, size_t raw_len, char *buf,
2036
+static int format_uuid_setting ( struct setting_type *type __unused,
2037
+				 const void *raw, size_t raw_len, char *buf,
1787 2038
 				 size_t len ) {
1788 2039
 	const union uuid *uuid = raw;
1789 2040
 
@@ -1798,40 +2049,27 @@ static int format_uuid_setting ( const void *raw, size_t raw_len, char *buf,
1798 2049
 /** UUID setting type */
1799 2050
 struct setting_type setting_type_uuid __setting_type = {
1800 2051
 	.name = "uuid",
1801
-	.parse = parse_uuid_setting,
1802 2052
 	.format = format_uuid_setting,
1803 2053
 };
1804 2054
 
1805
-/**
1806
- * Parse PCI bus:dev.fn setting value
1807
- *
1808
- * @v value		Formatted setting value
1809
- * @v buf		Buffer to contain raw value
1810
- * @v len		Length of buffer
1811
- * @ret len		Length of raw value, or negative error
1812
- */
1813
-static int parse_busdevfn_setting ( const char *value __unused,
1814
-				    void *buf __unused, size_t len __unused ) {
1815
-	return -ENOTSUP;
1816
-}
1817
-
1818 2055
 /**
1819 2056
  * Format PCI bus:dev.fn setting value
1820 2057
  *
2058
+ * @v type		Setting type
1821 2059
  * @v raw		Raw setting value
1822 2060
  * @v raw_len		Length of raw setting value
1823 2061
  * @v buf		Buffer to contain formatted value
1824 2062
  * @v len		Length of buffer
1825 2063
  * @ret len		Length of formatted value, or negative error
1826 2064
  */
1827
-static int format_busdevfn_setting ( const void *raw, size_t raw_len, char *buf,
2065
+static int format_busdevfn_setting ( struct setting_type *type __unused,
2066
+				     const void *raw, size_t raw_len, char *buf,
1828 2067
 				     size_t len ) {
1829
-	signed long dummy;
1830 2068
 	unsigned long busdevfn;
1831 2069
 	int check_len;
1832 2070
 
1833 2071
 	/* Extract numeric value */
1834
-	check_len = numeric_setting_value ( raw, raw_len, &dummy, &busdevfn );
2072
+	check_len = numeric_setting_value ( 0, raw, raw_len, &busdevfn );
1835 2073
 	if ( check_len < 0 )
1836 2074
 		return check_len;
1837 2075
 	assert ( check_len == ( int ) raw_len );
@@ -1844,7 +2082,6 @@ static int format_busdevfn_setting ( const void *raw, size_t raw_len, char *buf,
1844 2082
 /** PCI bus:dev.fn setting type */
1845 2083
 struct setting_type setting_type_busdevfn __setting_type = {
1846 2084
 	.name = "busdevfn",
1847
-	.parse = parse_busdevfn_setting,
1848 2085
 	.format = format_busdevfn_setting,
1849 2086
 };
1850 2087
 

+ 40
- 5
src/include/ipxe/settings.h View File

@@ -185,24 +185,47 @@ struct setting_type {
185 185
 	 * This is the name exposed to the user (e.g. "string").
186 186
 	 */
187 187
 	const char *name;
188
-	/** Parse formatted setting value
188
+	/** Parse formatted string to setting value
189 189
 	 *
190
+	 * @v type		Setting type
190 191
 	 * @v value		Formatted setting value
191 192
 	 * @v buf		Buffer to contain raw value
192 193
 	 * @v len		Length of buffer
193 194
 	 * @ret len		Length of raw value, or negative error
194 195
 	 */
195
-	int ( * parse ) ( const char *value, void *buf, size_t len );
196
-	/** Format setting value
196
+	int ( * parse ) ( struct setting_type *type, const char *value,
197
+			  void *buf, size_t len );
198
+	/** Format setting value as a string
197 199
 	 *
200
+	 * @v type		Setting type
198 201
 	 * @v raw		Raw setting value
199 202
 	 * @v raw_len		Length of raw setting value
200 203
 	 * @v buf		Buffer to contain formatted value
201 204
 	 * @v len		Length of buffer
202 205
 	 * @ret len		Length of formatted value, or negative error
203 206
 	 */
204
-	int ( * format ) ( const void *raw, size_t raw_len, char *buf,
205
-			   size_t len );
207
+	int ( * format ) ( struct setting_type *type, const void *raw,
208
+			   size_t raw_len, char *buf, size_t len );
209
+	/** Convert number to setting value
210
+	 *
211
+	 * @v type		Setting type
212
+	 * @v value		Numeric value
213
+	 * @v buf		Buffer to contain raw value
214
+	 * @v len		Length of buffer
215
+	 * @ret len		Length of raw value, or negative error
216
+	 */
217
+	int ( * denumerate ) ( struct setting_type *type, unsigned long value,
218
+			       void *buf, size_t len );
219
+	/** Convert setting value to number
220
+	 *
221
+	 * @v type		Setting type
222
+	 * @v raw		Raw setting value
223
+	 * @v raw_len		Length of raw setting value
224
+	 * @v value		Numeric value to fill in
225
+	 * @ret rc		Return status code
226
+	 */
227
+	int ( * numerate ) ( struct setting_type *type, const void *raw,
228
+			     size_t raw_len, unsigned long *value );
206 229
 };
207 230
 
208 231
 /** Configuration setting type table */
@@ -308,6 +331,14 @@ extern int parse_setting_name ( char *name, get_child_settings_t get_child,
308 331
 				struct setting *setting );
309 332
 extern int setting_name ( struct settings *settings, struct setting *setting,
310 333
 			  char *buf, size_t len );
334
+extern int setting_format ( struct setting_type *type, const void *raw,
335
+			    size_t raw_len, char *buf, size_t len );
336
+extern int setting_parse ( struct setting_type *type, const char *value,
337
+			   void *buf, size_t len );
338
+extern int setting_numerate ( struct setting_type *type, const void *raw,
339
+			      size_t raw_len, unsigned long *value );
340
+extern int setting_denumerate ( struct setting_type *type, unsigned long value,
341
+				void *buf, size_t len );
311 342
 extern int fetchf_setting ( struct settings *settings, struct setting *setting,
312 343
 			    char *buf, size_t len );
313 344
 extern int fetchf_setting_copy ( struct settings *settings,
@@ -315,6 +346,10 @@ extern int fetchf_setting_copy ( struct settings *settings,
315 346
 extern int storef_setting ( struct settings *settings,
316 347
 			    struct setting *setting,
317 348
 			    const char *value );
349
+extern int fetchn_setting ( struct settings *settings, struct setting *setting,
350
+			    unsigned long *value );
351
+extern int storen_setting ( struct settings *settings, struct setting *setting,
352
+			    unsigned long value );
318 353
 extern char * expand_settings ( const char *string );
319 354
 
320 355
 extern struct setting_type setting_type_string __setting_type;

+ 89
- 2
src/tests/settings_test.c View File

@@ -82,12 +82,63 @@ FILE_LICENCE ( GPL2_OR_LATER );
82 82
 	len = fetchf_setting ( settings, setting, actual,		\
83 83
 			       sizeof ( actual ) );			\
84 84
 	DBGC ( settings, "Fetched %s \"%s\" from:\n",			\
85
-	       (setting)->type->name, formatted );			\
85
+	       (setting)->type->name, actual );				\
86 86
 	DBGC_HDA ( settings, 0, raw, sizeof ( raw ) );			\
87 87
 	ok ( len == ( int ) ( sizeof ( actual ) - 1 ) );		\
88 88
 	ok ( strcmp ( actual, formatted ) == 0 );			\
89 89
 	} while ( 0 )
90 90
 
91
+/**
92
+ * Report a numeric-store test result
93
+ *
94
+ * @v settings		Settings block
95
+ * @v setting		Setting
96
+ * @v numeric		Numeric value
97
+ * @v raw_array		Expected raw value
98
+ */
99
+#define storen_ok( settings, setting, numeric, raw_array ) do {		\
100
+	const uint8_t expected[] = raw_array;				\
101
+	uint8_t actual[ sizeof ( expected ) ];				\
102
+	int len;							\
103
+									\
104
+	ok ( storen_setting ( settings, setting, numeric ) == 0 );	\
105
+	len = fetch_setting ( settings, setting, actual,		\
106
+			      sizeof ( actual ) );			\
107
+	if ( len >= 0 ) {						\
108
+		DBGC ( settings, "Stored %s %#lx, got:\n",		\
109
+		       (setting)->type->name,				\
110
+		       ( unsigned long ) numeric );			\
111
+		DBGC_HDA ( settings, 0, actual, len );			\
112
+	} else {							\
113
+		DBGC ( settings, "Stored %s %#lx, got error %s\n",	\
114
+		       (setting)->type->name,				\
115
+		       ( unsigned long ) numeric, strerror ( len ) );	\
116
+	}								\
117
+	ok ( len == ( int ) sizeof ( actual ) );			\
118
+	ok ( memcmp ( actual, expected, sizeof ( actual ) ) == 0 );	\
119
+	} while ( 0 )
120
+
121
+/**
122
+ * Report a numeric-fetch test result
123
+ *
124
+ * @v settings		Settings block
125
+ * @v setting		Setting
126
+ * @v raw_array		Raw array
127
+ * @v numeric		Expected numeric value
128
+ */
129
+#define fetchn_ok( settings, setting, raw_array, numeric ) do {		\
130
+	const uint8_t raw[] = raw_array;				\
131
+	unsigned long actual;						\
132
+									\
133
+	ok ( store_setting ( settings, setting, raw,			\
134
+			     sizeof ( raw ) ) == 0 );			\
135
+	ok ( fetchn_setting ( settings, setting, &actual ) == 0 );	\
136
+	DBGC ( settings, "Fetched %s %#lx from:\n",			\
137
+	       (setting)->type->name, actual );				\
138
+	DBGC_HDA ( settings, 0, raw, sizeof ( raw ) );			\
139
+	ok ( actual == ( unsigned long ) numeric );			\
140
+	} while ( 0 )
141
+
91 142
 /** Test generic settings block */
92 143
 struct generic_settings test_generic_settings = {
93 144
 	.settings = {
@@ -216,7 +267,7 @@ static void settings_test_exec ( void ) {
216 267
 	fetchf_ok ( &test_settings, &test_ipv4_setting,
217 268
 		    RAW ( 212, 13, 204, 60 ), "212.13.204.60" );
218 269
 
219
-	/* Integer setting types */
270
+	/* Integer setting types (as formatted strings) */
220 271
 	storef_ok ( &test_settings, &test_int8_setting,
221 272
 		    "54", RAW ( 54 ) );
222 273
 	storef_ok ( &test_settings, &test_int8_setting,
@@ -256,6 +307,42 @@ static void settings_test_exec ( void ) {
256 307
 	fetchf_ok ( &test_settings, &test_uint32_setting,
257 308
 		    RAW ( 0xf2, 0x37, 0xb2, 0x18 ), "0xf237b218" );
258 309
 
310
+	/* Integer setting types (as numeric values) */
311
+	storen_ok ( &test_settings, &test_int8_setting,
312
+		    72, RAW ( 72 ) );
313
+	storen_ok ( &test_settings, &test_int8_setting,
314
+		    0xabcd, RAW ( 0xcd ) );
315
+	fetchn_ok ( &test_settings, &test_int8_setting,
316
+		    RAW ( 0xfe ), -2 );
317
+	storen_ok ( &test_settings, &test_uint8_setting,
318
+		    84, RAW ( 84 ) );
319
+	fetchn_ok ( &test_settings, &test_uint8_setting,
320
+		    RAW ( 0xfe ), 0xfe );
321
+	storen_ok ( &test_settings, &test_int16_setting,
322
+		    0x87bd, RAW ( 0x87, 0xbd ) );
323
+	fetchn_ok ( &test_settings, &test_int16_setting,
324
+		    RAW ( 0x3d, 0x14 ), 0x3d14 );
325
+	fetchn_ok ( &test_settings, &test_int16_setting,
326
+		    RAW ( 0x80 ), -128 );
327
+	storen_ok ( &test_settings, &test_uint16_setting,
328
+		    1, RAW ( 0x00, 0x01 ) );
329
+	fetchn_ok ( &test_settings, &test_uint16_setting,
330
+		    RAW ( 0xbd, 0x87 ), 0xbd87 );
331
+	fetchn_ok ( &test_settings, &test_uint16_setting,
332
+		    RAW ( 0x80 ), 0x0080 );
333
+	storen_ok ( &test_settings, &test_int32_setting,
334
+		    0x0812bfd2, RAW ( 0x08, 0x12, 0xbf, 0xd2 ) );
335
+	fetchn_ok ( &test_settings, &test_int32_setting,
336
+		    RAW ( 0x43, 0x87, 0x91, 0xb4 ), 0x438791b4 );
337
+	fetchn_ok ( &test_settings, &test_int32_setting,
338
+		    RAW ( 0xff, 0xff, 0xfe ), -2 );
339
+	storen_ok ( &test_settings, &test_uint32_setting,
340
+		    0xb5927ab8, RAW ( 0xb5, 0x92, 0x7a, 0xb8 ) );
341
+	fetchn_ok ( &test_settings, &test_uint32_setting,
342
+		    RAW ( 0x98, 0xab, 0x41, 0x81 ), 0x98ab4181 );
343
+	fetchn_ok ( &test_settings, &test_uint32_setting,
344
+		    RAW ( 0xff, 0xff, 0xfe ), 0x00fffffe );
345
+
259 346
 	/* "hex" setting type */
260 347
 	storef_ok ( &test_settings, &test_hex_setting,
261 348
 		    "08:12:f5:22:90:1b:4b:47:a8:30:cb:4d:67:4c:d6:76",

Loading…
Cancel
Save