Print this page
4378 Clean up %C in *time() functions
438 need documentation for strftime %s flag
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libfru/libnvfru/nvfru.c
+++ new/usr/src/lib/libfru/libnvfru/nvfru.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 + * Copyright (c) 2014 Gary Mills
24 + *
23 25 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 26 */
25 27
26 28 #include <stdio.h>
27 29 #include <stdlib.h>
28 30 #include <stdint.h>
29 31 #include <strings.h>
30 32 #include <assert.h>
31 33 #include <pthread.h>
32 34 #include <sys/byteorder.h>
33 35 #include <sys/types.h>
34 36 #include <sys/nvpair.h>
35 37
36 38 #include "libfru.h"
37 39 #include "libfrup.h"
38 40 #include "fru_tag.h"
39 41 #include "libfrureg.h"
40 42 #include "nvfru.h"
41 43
42 44 #define NUM_ITER_BYTES 4
43 45 #define HEAD_ITER 0
44 46 #define TAIL_ITER 1
45 47 #define NUM_ITER 2
46 48 #define MAX_ITER 3
47 49 #define TIMESTRINGLEN 128
48 50
49 51 #define PARSE_TIME 1
50 52
51 53 static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
52 54
53 55
54 56
55 57 static void
56 58 convert_field(const uint8_t *field, const fru_regdef_t *def, const char *path,
57 59 nvlist_t *nv)
58 60 {
59 61 char timestring[TIMESTRINGLEN];
60 62 int i;
61 63 uint64_t value;
62 64 time_t timefield;
63 65
64 66 switch (def->dataType) {
65 67 case FDTYPE_Binary:
↓ open down ↓ |
33 lines elided |
↑ open up ↑ |
66 68 assert(def->payloadLen <= sizeof (value));
67 69 switch (def->dispType) {
68 70 #if PARSE_TIME == 1
69 71 case FDISP_Time:
70 72 if (def->payloadLen > sizeof (timefield)) {
71 73 /* too big for formatting */
72 74 return;
73 75 }
74 76 (void) memcpy(&timefield, field, sizeof (timefield));
75 77 timefield = BE_32(timefield);
76 - if (strftime(timestring, sizeof (timestring), "%C",
78 + if (strftime(timestring, sizeof (timestring), "%c",
77 79 localtime(&timefield)) == 0) {
78 80 /* buffer too small */
79 81 return;
80 82 }
81 83 (void) nvlist_add_string(nv, path, timestring);
82 84 return;
83 85 #endif
84 86
85 87 case FDISP_Binary:
86 88 case FDISP_Octal:
87 89 case FDISP_Decimal:
88 90 case FDISP_Hex:
89 91 default:
90 92 value = 0;
91 93 (void) memcpy((((uint8_t *)&value) +
92 94 sizeof (value) - def->payloadLen),
93 95 field, def->payloadLen);
94 96 value = BE_64(value);
95 97 switch (def->payloadLen) {
96 98 case 1:
97 99 (void) nvlist_add_uint8(nv, path,
98 100 (uint8_t)value);
99 101 break;
100 102 case 2:
101 103 (void) nvlist_add_uint16(nv, path,
102 104 (uint16_t)value);
103 105 break;
104 106 case 4:
105 107 (void) nvlist_add_uint32(nv, path,
106 108 (uint32_t)value);
107 109 break;
108 110 default:
109 111 (void) nvlist_add_uint64(nv, path, value);
110 112 }
111 113 return;
112 114 }
113 115
114 116 case FDTYPE_ASCII:
115 117 (void) nvlist_add_string(nv, path, (char *)field);
116 118 return;
117 119
118 120 case FDTYPE_Enumeration:
119 121 value = 0;
120 122 (void) memcpy((((uint8_t *)&value) + sizeof (value) -
121 123 def->payloadLen), field, def->payloadLen);
122 124 value = BE_64(value);
123 125 for (i = 0; i < def->enumCount; i++) {
124 126 if (def->enumTable[i].value == value) {
125 127 (void) nvlist_add_string(nv, path,
126 128 def->enumTable[i].text);
127 129 return;
128 130 }
129 131 }
130 132 }
131 133
132 134 /* nothing matched above, use byte array */
133 135 (void) nvlist_add_byte_array(nv, path, (uchar_t *)field,
134 136 def->payloadLen);
135 137 }
136 138
137 139
138 140
139 141 static void
140 142 convert_element(const uint8_t *data, const fru_regdef_t *def, char *ppath,
141 143 nvlist_t *nv, boolean_t from_iter)
142 144 {
143 145 int i;
144 146 char *path;
145 147
146 148 /* construct path */
147 149 if ((def->iterationCount == 0) &&
148 150 (def->iterationType != FRU_NOT_ITERATED)) {
149 151 path = ppath;
150 152 } else {
151 153 path = (char *)def->name;
152 154 }
153 155
154 156 /* iteration, record and field */
155 157 if (def->iterationCount) {
156 158 int iterlen, n;
157 159 uint8_t head, num;
158 160 fru_regdef_t newdef;
159 161 nvlist_t **nv_elems;
160 162 char num_str[32];
161 163
162 164 iterlen = (def->payloadLen - NUM_ITER_BYTES) /
163 165 def->iterationCount;
164 166
165 167 /*
166 168 * make a new element definition to describe the components of
167 169 * the iteration.
168 170 */
169 171 (void) memcpy(&newdef, def, sizeof (newdef));
170 172 newdef.iterationCount = 0;
171 173 newdef.payloadLen = iterlen;
172 174
173 175 /* validate the content of the iteration control bytes */
174 176 if ((data[HEAD_ITER] >= def->iterationCount) ||
175 177 (data[NUM_ITER] > def->iterationCount) ||
176 178 (data[MAX_ITER] != def->iterationCount)) {
177 179 /* invalid. show all iterations */
178 180 head = 0;
179 181 num = def->iterationCount;
180 182 } else {
181 183 head = data[HEAD_ITER];
182 184 num = data[NUM_ITER];
183 185 }
184 186
185 187 nv_elems = (nvlist_t **)malloc(num * sizeof (nvlist_t *));
186 188 if (!nv_elems)
187 189 return;
188 190 for (i = head, n = 0, data += sizeof (uint32_t); n < num;
189 191 i = ((i + 1) % def->iterationCount), n++) {
190 192 if (nvlist_alloc(&nv_elems[n], NV_UNIQUE_NAME, 0) != 0)
191 193 return;
192 194 (void) snprintf(num_str, sizeof (num_str), "%d", n);
193 195 convert_element((data + i*iterlen), &newdef, num_str,
194 196 nv_elems[n], B_TRUE);
195 197 }
196 198 (void) nvlist_add_nvlist_array(nv, path, nv_elems, num);
197 199
198 200 } else if (def->dataType == FDTYPE_Record) {
199 201 const fru_regdef_t *component;
200 202 nvlist_t *nv_record;
201 203
202 204 if (!from_iter) {
203 205 if (nvlist_alloc(&nv_record, NV_UNIQUE_NAME, 0) != 0) {
204 206 return;
205 207 }
206 208 } else {
207 209 nv_record = nv;
208 210 }
209 211
210 212 for (i = 0; i < def->enumCount; i++,
211 213 data += component->payloadLen) {
212 214 component = fru_reg_lookup_def_by_name(
213 215 def->enumTable[i].text);
214 216 convert_element(data, component, "", nv_record,
215 217 B_FALSE);
216 218 }
217 219
218 220 (void) nvlist_add_nvlist(nv, path, nv_record);
219 221
220 222 } else {
221 223 convert_field(data, def, path, nv);
222 224 }
223 225 }
224 226
225 227
226 228 static fru_regdef_t *
227 229 alloc_unknown_fru_regdef(void)
228 230 {
229 231 fru_regdef_t *p;
230 232
231 233 p = malloc(sizeof (fru_regdef_t));
232 234 if (!p) {
233 235 return (NULL);
234 236 }
235 237 p->version = REGDEF_VERSION;
236 238 p->name = NULL;
237 239 p->tagType = -1;
238 240 p->tagDense = -1;
239 241 p->payloadLen = -1;
240 242 p->dataLength = -1;
241 243 p->dataType = FDTYPE_ByteArray;
242 244 p->dispType = FDISP_Hex;
243 245 p->purgeable = FRU_WHICH_UNDEFINED;
244 246 p->relocatable = FRU_WHICH_UNDEFINED;
245 247 p->enumCount = 0;
246 248 p-> enumTable = NULL;
247 249 p->iterationCount = 0;
248 250 p->iterationType = FRU_NOT_ITERATED;
249 251 p->exampleString = NULL;
250 252
251 253 return (p);
252 254 }
253 255
254 256 static int
255 257 convert_packet(fru_tag_t *tag, uint8_t *payload, size_t length, void *args)
256 258 {
257 259 int tag_type;
258 260 size_t payload_length;
259 261 const fru_regdef_t *def;
260 262 nvlist_t *nv = (nvlist_t *)args;
261 263 char tagname[sizeof ("?_0123456789_0123456789")];
262 264 tag_type = get_tag_type(tag);
263 265 payload_length = 0;
264 266
265 267 /* check for unrecognized tag */
266 268 if ((tag_type == -1) ||
267 269 ((payload_length = get_payload_length(tag)) != length)) {
268 270 fru_regdef_t *unknown;
269 271
270 272 unknown = alloc_unknown_fru_regdef();
271 273 unknown->payloadLen = length;
272 274 unknown->dataLength = unknown->payloadLen;
273 275
274 276 if (tag_type == -1) {
275 277 (void) snprintf(tagname, sizeof (tagname),
276 278 "INVALID");
277 279 } else {
278 280 (void) snprintf(tagname, sizeof (tagname),
279 281 "%s_%u_%u_%u", get_tagtype_str(tag_type),
280 282 get_tag_dense(tag), payload_length, length);
281 283 }
282 284 unknown->name = tagname;
283 285 convert_element(payload, unknown, "", nv, B_FALSE);
284 286 free(unknown);
285 287
286 288 } else if ((def = fru_reg_lookup_def_by_tag(*tag)) == NULL) {
287 289 fru_regdef_t *unknown;
288 290
289 291 unknown = alloc_unknown_fru_regdef();
290 292 unknown->payloadLen = length;
291 293 unknown->dataLength = unknown->payloadLen;
292 294
293 295 (void) snprintf(tagname, sizeof (tagname), "%s_%u_%u",
294 296 get_tagtype_str(tag_type),
295 297 unknown->tagDense, payload_length);
296 298
297 299 unknown->name = tagname;
298 300 convert_element(payload, unknown, "", nv, B_FALSE);
299 301 free(unknown);
300 302
301 303 } else {
302 304
303 305 convert_element(payload, def, "", nv, B_FALSE);
304 306
305 307 }
306 308
307 309 return (FRU_SUCCESS);
308 310 }
309 311
310 312
311 313 static int
312 314 convert_packets_in_segment(fru_seghdl_t segment, void *args)
313 315 {
314 316 char *name;
315 317 int ret;
316 318 nvlist_t *nv = (nvlist_t *)args;
317 319 nvlist_t *nv_segment;
318 320
319 321 ret = fru_get_segment_name(segment, &name);
320 322 if (ret != FRU_SUCCESS) {
321 323 return (ret);
322 324 }
323 325
324 326 /* create a new nvlist for each segment */
325 327 ret = nvlist_alloc(&nv_segment, NV_UNIQUE_NAME, 0);
326 328 if (ret) {
327 329 free(name);
328 330 return (FRU_FAILURE);
329 331 }
330 332
331 333 /* convert the segment to an nvlist */
332 334 ret = fru_for_each_packet(segment, convert_packet, nv_segment);
333 335 if (ret != FRU_SUCCESS) {
334 336 nvlist_free(nv_segment);
335 337 free(name);
336 338 return (ret);
337 339 }
338 340
339 341 /* add the nvlist for this segment */
340 342 (void) nvlist_add_nvlist(nv, name, nv_segment);
341 343
342 344 free(name);
343 345
344 346 return (FRU_SUCCESS);
345 347 }
346 348
347 349
348 350 static int
349 351 convert_fru(fru_nodehdl_t hdl, nvlist_t **nvlist)
350 352 {
351 353 int err;
352 354 nvlist_t *nv;
353 355 fru_node_t fru_type;
354 356
355 357 if (fru_get_node_type(hdl, &fru_type) != FRU_SUCCESS) {
356 358 return (-1);
357 359 }
358 360
359 361 if (fru_type != FRU_NODE_CONTAINER) {
360 362 return (-1);
361 363 }
362 364
363 365 err = nvlist_alloc(&nv, NV_UNIQUE_NAME, 0);
364 366 if (err) {
365 367 return (err);
366 368 }
367 369
368 370 if (fru_for_each_segment(hdl, convert_packets_in_segment, nv) !=
369 371 FRU_SUCCESS) {
370 372 nvlist_free(nv);
371 373 return (-1);
372 374 }
373 375
374 376 *nvlist = nv;
375 377
376 378 return (0);
377 379 }
378 380
379 381
380 382 int
381 383 rawfru_to_nvlist(uint8_t *buffer, size_t bufsize, char *cont_type,
382 384 nvlist_t **nvlist)
383 385 {
384 386 fru_errno_t fru_err;
385 387 fru_nodehdl_t hdl;
386 388 int err;
387 389
388 390 (void) pthread_mutex_lock(&gLock);
389 391 fru_err = fru_open_data_source("raw", buffer, bufsize, cont_type,
390 392 NULL);
391 393 if (fru_err != FRU_SUCCESS) {
392 394 (void) pthread_mutex_unlock(&gLock);
393 395 return (-1);
394 396 }
395 397 fru_err = fru_get_root(&hdl);
396 398 if (fru_err != FRU_SUCCESS) {
397 399 (void) pthread_mutex_unlock(&gLock);
398 400 return (-1);
399 401 }
400 402
401 403 err = convert_fru(hdl, nvlist);
402 404
403 405 fru_close_data_source();
404 406
405 407 (void) pthread_mutex_unlock(&gLock);
406 408
407 409 return (err);
408 410 }
↓ open down ↓ |
322 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX