xref: /aosp_15_r20/external/coreboot/util/smmstoretool/data.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "data.h"
4 
5 #include <ctype.h>
6 #include <limits.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include "utils.h"
13 
print_data(const uint8_t data[],size_t data_size,enum data_type type)14 void print_data(const uint8_t data[], size_t data_size, enum data_type type)
15 {
16 	if (data_size == 0)
17 		return;
18 
19 	switch (type) {
20 	case DATA_TYPE_BOOL:
21 		bool value = false;
22 		for (size_t i = 0; i < data_size; ++i) {
23 			if (data[i] != 0) {
24 				value = true;
25 				break;
26 			}
27 		}
28 		printf("%s\n", value ? "true" : "false");
29 		break;
30 	case DATA_TYPE_UINT8:
31 		if (data_size != 1) {
32 			fprintf(stderr,
33 				"warning: expected size of 1, got %zu\n",
34 				data_size);
35 		}
36 
37 		if (data_size >= 1)
38 			printf("%u\n", *(uint8_t *)data);
39 		break;
40 	case DATA_TYPE_UINT16:
41 		if (data_size != 2) {
42 			fprintf(stderr,
43 				"warning: expected size of 2, got %zu\n",
44 				data_size);
45 		}
46 
47 		if (data_size >= 2)
48 			printf("%u\n", *(uint16_t *)data);
49 		break;
50 	case DATA_TYPE_UINT32:
51 		if (data_size != 4) {
52 			fprintf(stderr,
53 				"warning: expected size of 4, got %zu\n",
54 				data_size);
55 		}
56 
57 		if (data_size >= 4)
58 			printf("%u\n", *(uint32_t *)data);
59 		break;
60 	case DATA_TYPE_UINT64:
61 		if (data_size != 8) {
62 			fprintf(stderr,
63 				"warning: expected size of 8, got %zu\n",
64 				data_size);
65 		}
66 
67 		if (data_size >= 8)
68 			printf("%llu\n", (unsigned long long)*(uint64_t *)data);
69 		break;
70 	case DATA_TYPE_ASCII:
71 		for (size_t i = 0; i < data_size; ++i) {
72 			char c = data[i];
73 			if (isprint(c))
74 				printf("%c", c);
75 		}
76 		printf("\n");
77 		break;
78 	case DATA_TYPE_UNICODE:
79 		char *chars = to_chars((const CHAR16 *)data, data_size);
80 		printf("%s\n", chars);
81 		free(chars);
82 		break;
83 	case DATA_TYPE_RAW:
84 		fwrite(data, 1, data_size, stdout);
85 		break;
86 	}
87 }
88 
parse_uint(const char source[],const char type[],unsigned long long max,bool * failed)89 static uint64_t parse_uint(const char source[],
90 			   const char type[],
91 			   unsigned long long max,
92 			   bool *failed)
93 {
94 	char *end;
95 	unsigned long long uint = strtoull(source, &end, /*base=*/0);
96 	if (*end != '\0') {
97 		fprintf(stderr, "Trailing characters in \"%s\": %s\n",
98 			source, end);
99 		*failed = true;
100 		return 0;
101 	}
102 	if (uint > max) {
103 		fprintf(stderr, "Invalid %s value: %llu\n", type, uint);
104 		*failed = true;
105 		return 0;
106 	}
107 
108 	*failed = false;
109 	return uint;
110 }
111 
make_data(const char source[],size_t * data_size,enum data_type type)112 void *make_data(const char source[], size_t *data_size, enum data_type type)
113 {
114 	switch (type) {
115 	void *data;
116 	bool boolean;
117 	uint64_t uint;
118 	bool failed;
119 
120 	case DATA_TYPE_BOOL:
121 		if (str_eq(source, "true")) {
122 			boolean = true;
123 		} else if (str_eq(source, "false")) {
124 			boolean = false;
125 		} else {
126 			fprintf(stderr, "Invalid boolean value: \"%s\"\n",
127 				source);
128 			return NULL;
129 		}
130 
131 		*data_size = 1;
132 		data = xmalloc(*data_size);
133 		*(uint8_t *)data = boolean;
134 		return data;
135 	case DATA_TYPE_UINT8:
136 		uint = parse_uint(source, "uint8", UINT8_MAX, &failed);
137 		if (failed)
138 			return NULL;
139 
140 		*data_size = 1;
141 		data = xmalloc(*data_size);
142 		*(uint8_t *)data = uint;
143 		return data;
144 	case DATA_TYPE_UINT16:
145 		uint = parse_uint(source, "uint16", UINT16_MAX, &failed);
146 		if (failed)
147 			return NULL;
148 
149 		*data_size = 2;
150 		data = xmalloc(*data_size);
151 		*(uint16_t *)data = uint;
152 		return data;
153 	case DATA_TYPE_UINT32:
154 		uint = parse_uint(source, "uint32", UINT32_MAX, &failed);
155 		if (failed)
156 			return NULL;
157 
158 		*data_size = 4;
159 		data = xmalloc(*data_size);
160 		*(uint32_t *)data = uint;
161 		return data;
162 	case DATA_TYPE_UINT64:
163 		uint = parse_uint(source, "uint64", UINT64_MAX, &failed);
164 		if (failed)
165 			return NULL;
166 
167 		*data_size = 8;
168 		data = xmalloc(*data_size);
169 		*(uint64_t *)data = uint;
170 		return data;
171 	case DATA_TYPE_ASCII:
172 		*data_size = strlen(source) + 1;
173 		return strdup(source);
174 	case DATA_TYPE_UNICODE:
175 		return to_uchars(source, data_size);
176 	case DATA_TYPE_RAW:
177 		fprintf(stderr, "Raw data type is output only\n");
178 		return NULL;
179 	}
180 
181 	return NULL;
182 }
183 
parse_data_type(const char str[],enum data_type * type)184 bool parse_data_type(const char str[], enum data_type *type)
185 {
186 	if (str_eq(str, "bool"))
187 		*type = DATA_TYPE_BOOL;
188 	else if (str_eq(str, "uint8"))
189 		*type = DATA_TYPE_UINT8;
190 	else if (str_eq(str, "uint16"))
191 		*type = DATA_TYPE_UINT16;
192 	else if (str_eq(str, "uint32"))
193 		*type = DATA_TYPE_UINT32;
194 	else if (str_eq(str, "uint64"))
195 		*type = DATA_TYPE_UINT64;
196 	else if (str_eq(str, "ascii"))
197 		*type = DATA_TYPE_ASCII;
198 	else if (str_eq(str, "unicode"))
199 		*type = DATA_TYPE_UNICODE;
200 	else if (str_eq(str, "raw"))
201 		*type = DATA_TYPE_RAW;
202 	else
203 		return false;
204 
205 	return true;
206 }
207