xref: /openbmc/libcper/cper-utils.c (revision dd9e8d9847ea478c96b936361952e7ba2cdc832a)
11b0b00e3SLawrence Tang /**
21b0b00e3SLawrence Tang  * Describes utility functions for parsing CPER into JSON IR.
31b0b00e3SLawrence Tang  *
41b0b00e3SLawrence Tang  * Author: Lawrence.Tang@arm.com
51b0b00e3SLawrence Tang  **/
61b0b00e3SLawrence Tang 
71b0b00e3SLawrence Tang #include <stdio.h>
85202bbb4SLawrence Tang #include <json.h>
9ae8f6d9aSAushim Nagarkatti #include <string.h>
10e42fb487SThu Nguyen #include <libcper/Cper.h>
11e42fb487SThu Nguyen #include <libcper/cper-utils.h>
121b0b00e3SLawrence Tang 
131b0b00e3SLawrence Tang //The available severity types for CPER.
14e407b4c8SLawrence Tang const char *CPER_SEVERITY_TYPES[4] = { "Recoverable", "Fatal", "Corrected",
15e407b4c8SLawrence Tang 				       "Informational" };
161b0b00e3SLawrence Tang 
17a0865e38SLawrence Tang //Converts the given generic CPER error status to JSON IR.
18e407b4c8SLawrence Tang json_object *
cper_generic_error_status_to_ir(EFI_GENERIC_ERROR_STATUS * error_status)19e407b4c8SLawrence Tang cper_generic_error_status_to_ir(EFI_GENERIC_ERROR_STATUS *error_status)
20a0865e38SLawrence Tang {
21a0865e38SLawrence Tang 	json_object *error_status_ir = json_object_new_object();
22a0865e38SLawrence Tang 
23a0865e38SLawrence Tang 	//Error type.
24e407b4c8SLawrence Tang 	json_object_object_add(error_status_ir, "errorType",
25e407b4c8SLawrence Tang 			       integer_to_readable_pair_with_desc(
26e407b4c8SLawrence Tang 				       error_status->Type, 18,
27a0865e38SLawrence Tang 				       CPER_GENERIC_ERROR_TYPES_KEYS,
28a0865e38SLawrence Tang 				       CPER_GENERIC_ERROR_TYPES_VALUES,
29a0865e38SLawrence Tang 				       CPER_GENERIC_ERROR_TYPES_DESCRIPTIONS,
30a0865e38SLawrence Tang 				       "Unknown (Reserved)"));
31a0865e38SLawrence Tang 
32a0865e38SLawrence Tang 	//Boolean bit fields.
33e407b4c8SLawrence Tang 	json_object_object_add(
34e407b4c8SLawrence Tang 		error_status_ir, "addressSignal",
35e407b4c8SLawrence Tang 		json_object_new_boolean(error_status->AddressSignal));
36e407b4c8SLawrence Tang 	json_object_object_add(
37e407b4c8SLawrence Tang 		error_status_ir, "controlSignal",
38e407b4c8SLawrence Tang 		json_object_new_boolean(error_status->ControlSignal));
39e407b4c8SLawrence Tang 	json_object_object_add(
40e407b4c8SLawrence Tang 		error_status_ir, "dataSignal",
41e407b4c8SLawrence Tang 		json_object_new_boolean(error_status->DataSignal));
42e407b4c8SLawrence Tang 	json_object_object_add(
43e407b4c8SLawrence Tang 		error_status_ir, "detectedByResponder",
44e407b4c8SLawrence Tang 		json_object_new_boolean(error_status->DetectedByResponder));
45e407b4c8SLawrence Tang 	json_object_object_add(
46e407b4c8SLawrence Tang 		error_status_ir, "detectedByRequester",
47e407b4c8SLawrence Tang 		json_object_new_boolean(error_status->DetectedByRequester));
48e407b4c8SLawrence Tang 	json_object_object_add(
49e407b4c8SLawrence Tang 		error_status_ir, "firstError",
50e407b4c8SLawrence Tang 		json_object_new_boolean(error_status->FirstError));
51e407b4c8SLawrence Tang 	json_object_object_add(
52e407b4c8SLawrence Tang 		error_status_ir, "overflowDroppedLogs",
53e407b4c8SLawrence Tang 		json_object_new_boolean(error_status->OverflowNotLogged));
54a0865e38SLawrence Tang 
55a0865e38SLawrence Tang 	return error_status_ir;
56a0865e38SLawrence Tang }
57a0865e38SLawrence Tang 
583b7f45b5SLawrence Tang //Converts the given CPER-JSON generic error status into a CPER structure.
ir_generic_error_status_to_cper(json_object * error_status,EFI_GENERIC_ERROR_STATUS * error_status_cper)59e407b4c8SLawrence Tang void ir_generic_error_status_to_cper(
60e407b4c8SLawrence Tang 	json_object *error_status, EFI_GENERIC_ERROR_STATUS *error_status_cper)
613b7f45b5SLawrence Tang {
62e407b4c8SLawrence Tang 	error_status_cper->Type = readable_pair_to_integer(
63e407b4c8SLawrence Tang 		json_object_object_get(error_status, "errorType"));
64e407b4c8SLawrence Tang 	error_status_cper->AddressSignal = json_object_get_boolean(
65e407b4c8SLawrence Tang 		json_object_object_get(error_status, "addressSignal"));
66e407b4c8SLawrence Tang 	error_status_cper->ControlSignal = json_object_get_boolean(
67e407b4c8SLawrence Tang 		json_object_object_get(error_status, "controlSignal"));
68e407b4c8SLawrence Tang 	error_status_cper->DataSignal = json_object_get_boolean(
69e407b4c8SLawrence Tang 		json_object_object_get(error_status, "dataSignal"));
70e407b4c8SLawrence Tang 	error_status_cper->DetectedByResponder = json_object_get_boolean(
71e407b4c8SLawrence Tang 		json_object_object_get(error_status, "detectedByResponder"));
72e407b4c8SLawrence Tang 	error_status_cper->DetectedByRequester = json_object_get_boolean(
73e407b4c8SLawrence Tang 		json_object_object_get(error_status, "detectedByRequester"));
74e407b4c8SLawrence Tang 	error_status_cper->FirstError = json_object_get_boolean(
75e407b4c8SLawrence Tang 		json_object_object_get(error_status, "firstError"));
76e407b4c8SLawrence Tang 	error_status_cper->OverflowNotLogged = json_object_get_boolean(
77e407b4c8SLawrence Tang 		json_object_object_get(error_status, "overflowDroppedLogs"));
783b7f45b5SLawrence Tang }
793b7f45b5SLawrence Tang 
807f21db6cSLawrence Tang //Converts a single uniform struct of UINT64s into intermediate JSON IR format, given names for each field in byte order.
uniform_struct64_to_ir(UINT64 * start,int len,const char * names[])817f21db6cSLawrence Tang json_object *uniform_struct64_to_ir(UINT64 *start, int len, const char *names[])
827f21db6cSLawrence Tang {
837f21db6cSLawrence Tang 	json_object *result = json_object_new_object();
847f21db6cSLawrence Tang 
857f21db6cSLawrence Tang 	UINT64 *cur = start;
86e407b4c8SLawrence Tang 	for (int i = 0; i < len; i++) {
87e407b4c8SLawrence Tang 		json_object_object_add(result, names[i],
88e407b4c8SLawrence Tang 				       json_object_new_uint64(*cur));
897f21db6cSLawrence Tang 		cur++;
907f21db6cSLawrence Tang 	}
917f21db6cSLawrence Tang 
927f21db6cSLawrence Tang 	return result;
937f21db6cSLawrence Tang }
947f21db6cSLawrence Tang 
957f21db6cSLawrence Tang //Converts a single uniform struct of UINT32s into intermediate JSON IR format, given names for each field in byte order.
uniform_struct_to_ir(UINT32 * start,int len,const char * names[])967f21db6cSLawrence Tang json_object *uniform_struct_to_ir(UINT32 *start, int len, const char *names[])
977f21db6cSLawrence Tang {
987f21db6cSLawrence Tang 	json_object *result = json_object_new_object();
997f21db6cSLawrence Tang 
1007f21db6cSLawrence Tang 	UINT32 *cur = start;
101e407b4c8SLawrence Tang 	for (int i = 0; i < len; i++) {
102ae8f6d9aSAushim Nagarkatti 		UINT32 value;
103ae8f6d9aSAushim Nagarkatti 		memcpy(&value, cur, sizeof(UINT32));
104e407b4c8SLawrence Tang 		json_object_object_add(result, names[i],
105ae8f6d9aSAushim Nagarkatti 				       json_object_new_uint64(value));
1067f21db6cSLawrence Tang 		cur++;
1077f21db6cSLawrence Tang 	}
1087f21db6cSLawrence Tang 
1097f21db6cSLawrence Tang 	return result;
1107f21db6cSLawrence Tang }
1117f21db6cSLawrence Tang 
11271570a2aSLawrence Tang //Converts a single object containing UINT32s into a uniform struct.
ir_to_uniform_struct64(json_object * ir,UINT64 * start,int len,const char * names[])113e407b4c8SLawrence Tang void ir_to_uniform_struct64(json_object *ir, UINT64 *start, int len,
114e407b4c8SLawrence Tang 			    const char *names[])
11571570a2aSLawrence Tang {
11671570a2aSLawrence Tang 	UINT64 *cur = start;
117e407b4c8SLawrence Tang 	for (int i = 0; i < len; i++) {
118e407b4c8SLawrence Tang 		*cur = json_object_get_uint64(
119e407b4c8SLawrence Tang 			json_object_object_get(ir, names[i]));
12071570a2aSLawrence Tang 		cur++;
12171570a2aSLawrence Tang 	}
12271570a2aSLawrence Tang }
12371570a2aSLawrence Tang 
12471570a2aSLawrence Tang //Converts a single object containing UINT32s into a uniform struct.
ir_to_uniform_struct(json_object * ir,UINT32 * start,int len,const char * names[])125e407b4c8SLawrence Tang void ir_to_uniform_struct(json_object *ir, UINT32 *start, int len,
126e407b4c8SLawrence Tang 			  const char *names[])
12771570a2aSLawrence Tang {
12871570a2aSLawrence Tang 	UINT32 *cur = start;
129e407b4c8SLawrence Tang 	for (int i = 0; i < len; i++) {
130e407b4c8SLawrence Tang 		*cur = (UINT32)json_object_get_uint64(
131e407b4c8SLawrence Tang 			json_object_object_get(ir, names[i]));
13271570a2aSLawrence Tang 		cur++;
13371570a2aSLawrence Tang 	}
13471570a2aSLawrence Tang }
13571570a2aSLawrence Tang 
1363c43f743SLawrence Tang //Converts a single integer value to an object containing a value, and a readable name if possible.
integer_to_readable_pair(UINT64 value,int len,const int keys[],const char * values[],const char * default_value)137b35d957eSEd Tanous json_object *integer_to_readable_pair(UINT64 value, int len, const int keys[],
138e407b4c8SLawrence Tang 				      const char *values[],
139e407b4c8SLawrence Tang 				      const char *default_value)
1403c43f743SLawrence Tang {
1413c43f743SLawrence Tang 	json_object *result = json_object_new_object();
1423c878352SLawrence Tang 	json_object_object_add(result, "value", json_object_new_uint64(value));
1433c43f743SLawrence Tang 
1443c43f743SLawrence Tang 	//Search for human readable name, add.
145794312c8SLawrence Tang 	const char *name = default_value;
146e407b4c8SLawrence Tang 	for (int i = 0; i < len; i++) {
147f8fc7052SJohn Chung 		if ((UINT64)keys[i] == value) {
1483c43f743SLawrence Tang 			name = values[i];
1493c43f743SLawrence Tang 		}
150f8fc7052SJohn Chung 	}
1513c43f743SLawrence Tang 
1523c43f743SLawrence Tang 	json_object_object_add(result, "name", json_object_new_string(name));
1533c43f743SLawrence Tang 	return result;
1543c43f743SLawrence Tang }
1553c43f743SLawrence Tang 
1567f21db6cSLawrence Tang //Converts a single integer value to an object containing a value, readable name and description if possible.
integer_to_readable_pair_with_desc(int value,int len,const int keys[],const char * values[],const char * descriptions[],const char * default_value)157b35d957eSEd Tanous json_object *integer_to_readable_pair_with_desc(int value, int len,
158b35d957eSEd Tanous 						const int keys[],
159e407b4c8SLawrence Tang 						const char *values[],
160e407b4c8SLawrence Tang 						const char *descriptions[],
161e407b4c8SLawrence Tang 						const char *default_value)
1627f21db6cSLawrence Tang {
1637f21db6cSLawrence Tang 	json_object *result = json_object_new_object();
1647f21db6cSLawrence Tang 	json_object_object_add(result, "value", json_object_new_int(value));
1657f21db6cSLawrence Tang 
1667f21db6cSLawrence Tang 	//Search for human readable name, add.
1677f21db6cSLawrence Tang 	const char *name = default_value;
168e407b4c8SLawrence Tang 	for (int i = 0; i < len; i++) {
169e407b4c8SLawrence Tang 		if (keys[i] == value) {
1707f21db6cSLawrence Tang 			name = values[i];
171e407b4c8SLawrence Tang 			json_object_object_add(
172e407b4c8SLawrence Tang 				result, "description",
173e407b4c8SLawrence Tang 				json_object_new_string(descriptions[i]));
1747f21db6cSLawrence Tang 		}
1757f21db6cSLawrence Tang 	}
1767f21db6cSLawrence Tang 
1777f21db6cSLawrence Tang 	json_object_object_add(result, "name", json_object_new_string(name));
1787f21db6cSLawrence Tang 	return result;
1797f21db6cSLawrence Tang }
1807f21db6cSLawrence Tang 
181b44314c7SLawrence Tang //Returns a single UINT64 value from the given readable pair object.
182b44314c7SLawrence Tang //Assumes the integer value is held in the "value" field.
readable_pair_to_integer(json_object * pair)183b44314c7SLawrence Tang UINT64 readable_pair_to_integer(json_object *pair)
184b44314c7SLawrence Tang {
185b44314c7SLawrence Tang 	return json_object_get_uint64(json_object_object_get(pair, "value"));
186b44314c7SLawrence Tang }
187b44314c7SLawrence Tang 
188794312c8SLawrence Tang //Converts the given 64 bit bitfield to IR, assuming bit 0 starts on the left.
bitfield_to_ir(UINT64 bitfield,int num_fields,const char * names[])189e407b4c8SLawrence Tang json_object *bitfield_to_ir(UINT64 bitfield, int num_fields,
190e407b4c8SLawrence Tang 			    const char *names[])
191794312c8SLawrence Tang {
192794312c8SLawrence Tang 	json_object *result = json_object_new_object();
193e407b4c8SLawrence Tang 	for (int i = 0; i < num_fields; i++) {
194e407b4c8SLawrence Tang 		json_object_object_add(result, names[i],
195e407b4c8SLawrence Tang 				       json_object_new_boolean((bitfield >> i) &
196f8fc7052SJohn Chung 							       0x1));
197794312c8SLawrence Tang 	}
198794312c8SLawrence Tang 
199794312c8SLawrence Tang 	return result;
200794312c8SLawrence Tang }
201794312c8SLawrence Tang 
202ae8f6d9aSAushim Nagarkatti //Filters properties based on Validation Bits.
203ae8f6d9aSAushim Nagarkatti // Refer to CPER spec for vbit_idx to be passed here.
add_to_valid_bitfield(ValidationTypes * val,int vbit_idx)204ae8f6d9aSAushim Nagarkatti void add_to_valid_bitfield(ValidationTypes *val, int vbit_idx)
205ae8f6d9aSAushim Nagarkatti {
206ae8f6d9aSAushim Nagarkatti 	switch (val->size) {
207ae8f6d9aSAushim Nagarkatti 	case UINT_8T:
208ae8f6d9aSAushim Nagarkatti 		val->value.ui8 |= (0x01 << vbit_idx);
209ae8f6d9aSAushim Nagarkatti 		break;
210ae8f6d9aSAushim Nagarkatti 	case UINT_16T:
211ae8f6d9aSAushim Nagarkatti 		val->value.ui16 |= (0x01 << vbit_idx);
212ae8f6d9aSAushim Nagarkatti 		break;
213ae8f6d9aSAushim Nagarkatti 	case UINT_32T:
214ae8f6d9aSAushim Nagarkatti 		val->value.ui32 |= (0x01 << vbit_idx);
215ae8f6d9aSAushim Nagarkatti 		break;
216ae8f6d9aSAushim Nagarkatti 	case UINT_64T:
217ae8f6d9aSAushim Nagarkatti 		val->value.ui64 |= (0x01 << vbit_idx);
218ae8f6d9aSAushim Nagarkatti 		break;
219ae8f6d9aSAushim Nagarkatti 	default:
220ae8f6d9aSAushim Nagarkatti 		printf("IR to CPER: Unknown validation bits size passed, Enum IntType=%d",
221ae8f6d9aSAushim Nagarkatti 		       val->size);
222ae8f6d9aSAushim Nagarkatti 	}
223ae8f6d9aSAushim Nagarkatti }
224ae8f6d9aSAushim Nagarkatti 
225b44314c7SLawrence Tang //Converts the given IR bitfield into a standard UINT64 bitfield, with fields beginning from bit 0.
ir_to_bitfield(json_object * ir,int num_fields,const char * names[])226b44314c7SLawrence Tang UINT64 ir_to_bitfield(json_object *ir, int num_fields, const char *names[])
227b44314c7SLawrence Tang {
228b44314c7SLawrence Tang 	UINT64 result = 0x0;
229e407b4c8SLawrence Tang 	for (int i = 0; i < num_fields; i++) {
230e407b4c8SLawrence Tang 		if (json_object_get_boolean(
231f8fc7052SJohn Chung 			    json_object_object_get(ir, names[i]))) {
232b44314c7SLawrence Tang 			result |= (0x1 << i);
233b44314c7SLawrence Tang 		}
234f8fc7052SJohn Chung 	}
235b44314c7SLawrence Tang 
236b44314c7SLawrence Tang 	return result;
237b44314c7SLawrence Tang }
238b44314c7SLawrence Tang 
239ae8f6d9aSAushim Nagarkatti // Filters properties based on Validation Bits.
240ae8f6d9aSAushim Nagarkatti // Refer to CPER spec for vbit_idx to be passed here.
241ae8f6d9aSAushim Nagarkatti // Overload function for 16, 32, 64b
isvalid_prop_to_ir(ValidationTypes * val,int vbit_idx)242ae8f6d9aSAushim Nagarkatti bool isvalid_prop_to_ir(ValidationTypes *val, int vbit_idx)
243ae8f6d9aSAushim Nagarkatti {
244*dd9e8d98SAushim Nagarkatti // If the option is enabled, output invalid properties
245*dd9e8d98SAushim Nagarkatti // as well as valid ones.
246*dd9e8d98SAushim Nagarkatti #ifdef OUTPUT_ALL_PROPERTIES
247*dd9e8d98SAushim Nagarkatti 	return true;
248*dd9e8d98SAushim Nagarkatti #endif //OUTPUT_ALL_PROPERTIES
249ae8f6d9aSAushim Nagarkatti 	UINT64 vbit_mask = 0x01 << vbit_idx;
250ae8f6d9aSAushim Nagarkatti 	switch (val->size) {
251ae8f6d9aSAushim Nagarkatti 	case UINT_16T:
252ae8f6d9aSAushim Nagarkatti 		return (vbit_mask & val->value.ui16);
253ae8f6d9aSAushim Nagarkatti 
254ae8f6d9aSAushim Nagarkatti 	case UINT_32T:
255ae8f6d9aSAushim Nagarkatti 		return (vbit_mask & val->value.ui32);
256ae8f6d9aSAushim Nagarkatti 
257ae8f6d9aSAushim Nagarkatti 	case UINT_64T:
258ae8f6d9aSAushim Nagarkatti 		return (vbit_mask & val->value.ui64);
259ae8f6d9aSAushim Nagarkatti 
260ae8f6d9aSAushim Nagarkatti 	default:
261ae8f6d9aSAushim Nagarkatti 		printf("CPER to IR:Unknown validation bits size passed. Enum IntType: %d",
262ae8f6d9aSAushim Nagarkatti 		       val->size);
263ae8f6d9aSAushim Nagarkatti 	}
264ae8f6d9aSAushim Nagarkatti 	return 0;
265ae8f6d9aSAushim Nagarkatti }
266ae8f6d9aSAushim Nagarkatti 
print_val(ValidationTypes * val)267ae8f6d9aSAushim Nagarkatti void print_val(ValidationTypes *val)
268ae8f6d9aSAushim Nagarkatti {
269ae8f6d9aSAushim Nagarkatti 	switch (val->size) {
270ae8f6d9aSAushim Nagarkatti 	case UINT_8T:
271ae8f6d9aSAushim Nagarkatti 		printf("Validation bits: %x\n", val->value.ui8);
272ae8f6d9aSAushim Nagarkatti 		break;
273ae8f6d9aSAushim Nagarkatti 	case UINT_16T:
274ae8f6d9aSAushim Nagarkatti 		printf("Validation bits: %x\n", val->value.ui16);
275ae8f6d9aSAushim Nagarkatti 		break;
276ae8f6d9aSAushim Nagarkatti 
277ae8f6d9aSAushim Nagarkatti 	case UINT_32T:
278ae8f6d9aSAushim Nagarkatti 		printf("Validation bits: %x\n", val->value.ui32);
279ae8f6d9aSAushim Nagarkatti 		break;
280ae8f6d9aSAushim Nagarkatti 
281ae8f6d9aSAushim Nagarkatti 	case UINT_64T:
282ae8f6d9aSAushim Nagarkatti 		printf("Validation bits: %llx\n", val->value.ui64);
283ae8f6d9aSAushim Nagarkatti 		break;
284ae8f6d9aSAushim Nagarkatti 
285ae8f6d9aSAushim Nagarkatti 	default:
286ae8f6d9aSAushim Nagarkatti 		printf("CPER to IR:Unknown validation bits size passed. Enum IntType: %d",
287ae8f6d9aSAushim Nagarkatti 		       val->size);
288ae8f6d9aSAushim Nagarkatti 	}
289ae8f6d9aSAushim Nagarkatti }
290ae8f6d9aSAushim Nagarkatti 
291e18aaee9SLawrence Tang //Converts the given UINT64 array into a JSON IR array, given the length.
uint64_array_to_ir_array(UINT64 * array,int len)292e18aaee9SLawrence Tang json_object *uint64_array_to_ir_array(UINT64 *array, int len)
293e18aaee9SLawrence Tang {
294e18aaee9SLawrence Tang 	json_object *array_ir = json_object_new_array();
295f8fc7052SJohn Chung 	for (int i = 0; i < len; i++) {
296e407b4c8SLawrence Tang 		json_object_array_add(array_ir,
297e407b4c8SLawrence Tang 				      json_object_new_uint64(array[i]));
298f8fc7052SJohn Chung 	}
299e18aaee9SLawrence Tang 	return array_ir;
300e18aaee9SLawrence Tang }
301794312c8SLawrence Tang 
3021b0b00e3SLawrence Tang //Converts a single UINT16 revision number into JSON IR representation.
revision_to_ir(UINT16 revision)3031b0b00e3SLawrence Tang json_object *revision_to_ir(UINT16 revision)
3041b0b00e3SLawrence Tang {
3051b0b00e3SLawrence Tang 	json_object *revision_info = json_object_new_object();
306e407b4c8SLawrence Tang 	json_object_object_add(revision_info, "major",
307e407b4c8SLawrence Tang 			       json_object_new_int(revision >> 8));
308e407b4c8SLawrence Tang 	json_object_object_add(revision_info, "minor",
309e407b4c8SLawrence Tang 			       json_object_new_int(revision & 0xFF));
3101b0b00e3SLawrence Tang 	return revision_info;
3111b0b00e3SLawrence Tang }
3121b0b00e3SLawrence Tang 
3131b0b00e3SLawrence Tang //Returns the appropriate string for the given integer severity.
severity_to_string(UINT32 severity)31402c801a5SLawrence Tang const char *severity_to_string(UINT32 severity)
3151b0b00e3SLawrence Tang {
3161b0b00e3SLawrence Tang 	return severity < 4 ? CPER_SEVERITY_TYPES[severity] : "Unknown";
3171b0b00e3SLawrence Tang }
3181b0b00e3SLawrence Tang 
319b44314c7SLawrence Tang //Converts a single EFI timestamp to string, at the given output.
320b44314c7SLawrence Tang //Output must be at least TIMESTAMP_LENGTH bytes long.
timestamp_to_string(char * out,int out_len,EFI_ERROR_TIME_STAMP * timestamp)32113f099ffSEd Tanous void timestamp_to_string(char *out, int out_len,
32213f099ffSEd Tanous 			 EFI_ERROR_TIME_STAMP *timestamp)
323b44314c7SLawrence Tang {
32413f099ffSEd Tanous 	int written = snprintf(
32513f099ffSEd Tanous 		out, out_len,
32613f099ffSEd Tanous 		"%02hhu%02hhu-%02hhu-%02hhuT%02hhu:%02hhu:%02hhu+00:00",
327e407b4c8SLawrence Tang 		bcd_to_int(timestamp->Century) %
328e407b4c8SLawrence Tang 			100,			   //Cannot go to three digits.
329aacf0e26SLawrence Tang 		bcd_to_int(timestamp->Year) % 100, //Cannot go to three digits.
330e407b4c8SLawrence Tang 		bcd_to_int(timestamp->Month), bcd_to_int(timestamp->Day),
331e407b4c8SLawrence Tang 		bcd_to_int(timestamp->Hours), bcd_to_int(timestamp->Minutes),
332aacf0e26SLawrence Tang 		bcd_to_int(timestamp->Seconds));
33313f099ffSEd Tanous 
33413f099ffSEd Tanous 	if (written < 0 || written >= out_len) {
33513f099ffSEd Tanous 		printf("Timestamp buffer of insufficient size\n");
33613f099ffSEd Tanous 	}
337b44314c7SLawrence Tang }
338b44314c7SLawrence Tang 
339b44314c7SLawrence Tang //Converts a single timestamp string to an EFI timestamp.
string_to_timestamp(EFI_ERROR_TIME_STAMP * out,const char * timestamp)340b44314c7SLawrence Tang void string_to_timestamp(EFI_ERROR_TIME_STAMP *out, const char *timestamp)
341b44314c7SLawrence Tang {
3420cb33793SLawrence Tang 	//Ignore invalid timestamps.
343f8fc7052SJohn Chung 	if (timestamp == NULL) {
3440cb33793SLawrence Tang 		return;
345f8fc7052SJohn Chung 	}
3460cb33793SLawrence Tang 
347de7dd061SAushim Nagarkatti 	sscanf(timestamp, "%2hhu%2hhu-%hhu-%hhuT%hhu:%hhu:%hhu+00:00",
348e407b4c8SLawrence Tang 	       &out->Century, &out->Year, &out->Month, &out->Day, &out->Hours,
349e407b4c8SLawrence Tang 	       &out->Minutes, &out->Seconds);
350aacf0e26SLawrence Tang 
351aacf0e26SLawrence Tang 	//Convert back to BCD.
352aacf0e26SLawrence Tang 	out->Century = int_to_bcd(out->Century);
353aacf0e26SLawrence Tang 	out->Year = int_to_bcd(out->Year);
354aacf0e26SLawrence Tang 	out->Month = int_to_bcd(out->Month);
355aacf0e26SLawrence Tang 	out->Day = int_to_bcd(out->Day);
356aacf0e26SLawrence Tang 	out->Hours = int_to_bcd(out->Hours);
357aacf0e26SLawrence Tang 	out->Minutes = int_to_bcd(out->Minutes);
358aacf0e26SLawrence Tang 	out->Seconds = int_to_bcd(out->Seconds);
359b44314c7SLawrence Tang }
360b44314c7SLawrence Tang 
3611b0b00e3SLawrence Tang //Helper function to convert an EDK EFI GUID into a string for intermediate use.
guid_to_string(char * out,EFI_GUID * guid)3621b0b00e3SLawrence Tang void guid_to_string(char *out, EFI_GUID *guid)
3631b0b00e3SLawrence Tang {
3647623a6e7SKarthik Rajagopalan 	sprintf(out, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
365e407b4c8SLawrence Tang 		guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
366e407b4c8SLawrence Tang 		guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
367e407b4c8SLawrence Tang 		guid->Data4[5], guid->Data4[6], guid->Data4[7]);
3681b0b00e3SLawrence Tang }
3691b0b00e3SLawrence Tang 
370b44314c7SLawrence Tang //Helper function to convert a string into an EDK EFI GUID.
string_to_guid(EFI_GUID * out,const char * guid)371b44314c7SLawrence Tang void string_to_guid(EFI_GUID *out, const char *guid)
372b44314c7SLawrence Tang {
3730cb33793SLawrence Tang 	//Ignore invalid GUIDs.
374f8fc7052SJohn Chung 	if (guid == NULL) {
3750cb33793SLawrence Tang 		return;
376f8fc7052SJohn Chung 	}
3770cb33793SLawrence Tang 
378e407b4c8SLawrence Tang 	sscanf(guid,
3797623a6e7SKarthik Rajagopalan 	       "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
380e407b4c8SLawrence Tang 	       &out->Data1, &out->Data2, &out->Data3, out->Data4,
381e407b4c8SLawrence Tang 	       out->Data4 + 1, out->Data4 + 2, out->Data4 + 3, out->Data4 + 4,
382e407b4c8SLawrence Tang 	       out->Data4 + 5, out->Data4 + 6, out->Data4 + 7);
383b44314c7SLawrence Tang }
384b44314c7SLawrence Tang 
3851b0b00e3SLawrence Tang //Returns one if two EFI GUIDs are equal, zero otherwise.
guid_equal(EFI_GUID * a,EFI_GUID * b)3861b0b00e3SLawrence Tang int guid_equal(EFI_GUID *a, EFI_GUID *b)
3871b0b00e3SLawrence Tang {
3881b0b00e3SLawrence Tang 	//Check top base 3 components.
389e407b4c8SLawrence Tang 	if (a->Data1 != b->Data1 || a->Data2 != b->Data2 ||
390e407b4c8SLawrence Tang 	    a->Data3 != b->Data3) {
3911b0b00e3SLawrence Tang 		return 0;
3921b0b00e3SLawrence Tang 	}
3931b0b00e3SLawrence Tang 
3941b0b00e3SLawrence Tang 	//Check Data4 array for equality.
395e407b4c8SLawrence Tang 	for (int i = 0; i < 8; i++) {
396f8fc7052SJohn Chung 		if (a->Data4[i] != b->Data4[i]) {
3971b0b00e3SLawrence Tang 			return 0;
3981b0b00e3SLawrence Tang 		}
399f8fc7052SJohn Chung 	}
4001b0b00e3SLawrence Tang 
4011b0b00e3SLawrence Tang 	return 1;
4021b0b00e3SLawrence Tang }
403