1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 #include <picl.h>
29 #include <limits.h>
30 #include <alloca.h>
31 #include <stdarg.h>
32 #include "smc_if.h"
33 #include "fru_access_impl.h"
34
35 #pragma init(initialize_fruaccess) /* .init section */
36
37 /*
38 * This module translates all the frudata plugin requests into platform
39 * specific commands and provides information back to frudata plugin.
40 */
41
42 /*
43 * precedence for format.
44 * define an ENV variable (SUNW_FRUACCESS_IPMI_PRECEDENCE) to make
45 * ipmi format has more precedence than sun format.
46 */
47 static int precedence = SUN_FORMAT; /* by default */
48 #define FRUACCESS_PRECEDENCE "SUNW_FRUACCESS_IPMI_PRECEDENCE"
49
50 extern ssize_t pread_new(int, void *, size_t, off_t, format_t *);
51 extern ssize_t pwrite_new(int, const void *, size_t, off_t, format_t *);
52 extern int get_manr(format_t *, payload_t *);
53 extern int is_fru_data_available(int, int, format_t *);
54 extern picl_errno_t fruaccess_platmod_init_format(uint8_t, format_t *);
55 extern int fruaccess_platmod_check_chassis();
56 extern int fruaccess_platmod_check_fru(picl_nodehdl_t parenth);
57
58 static container_hdl_t sun_fru_open_container(picl_nodehdl_t);
59 static int sun_fru_close_container(container_hdl_t);
60 static int sun_fru_get_num_sections(container_hdl_t, door_cred_t *);
61 static int sun_fru_get_sections(container_hdl_t, section_t *,
62 int, door_cred_t *);
63 static int sun_fru_get_num_segments(section_hdl_t, door_cred_t *);
64 static int sun_fru_get_segments(section_hdl_t, segment_t *,
65 int, door_cred_t *);
66 static int sun_fru_add_segment(section_hdl_t, segment_t *,
67 section_hdl_t *, door_cred_t *);
68 static int sun_fru_delete_segment(segment_hdl_t, section_hdl_t *,
69 door_cred_t *);
70 static ssize_t sun_fru_read_segment(segment_hdl_t, void *, size_t,
71 door_cred_t *);
72 static int sun_fru_write_segment(segment_hdl_t, const void *, size_t,
73 segment_hdl_t *, door_cred_t *);
74 static int sun_fru_get_num_packets(segment_hdl_t, door_cred_t *);
75 static int sun_fru_get_packets(segment_hdl_t, packet_t *,
76 int, door_cred_t *);
77 static ssize_t sun_fru_get_payload(packet_hdl_t, void *, size_t,
78 door_cred_t *);
79 static int sun_fru_update_payload(packet_hdl_t, const void *, size_t,
80 packet_hdl_t *, door_cred_t *);
81 static int sun_fru_append_packet(segment_hdl_t, packet_t *,
82 const void *, size_t, segment_hdl_t *,
83 door_cred_t *);
84 static int sun_fru_delete_packet(packet_hdl_t, segment_hdl_t *, door_cred_t *);
85
86 static container_hdl_t ipmi_fru_open_container(picl_nodehdl_t);
87 static int ipmi_fru_close_container(container_hdl_t);
88 static int ipmi_fru_get_num_sections(container_hdl_t, door_cred_t *);
89 static int ipmi_fru_get_sections(container_hdl_t, section_t *,
90 int, door_cred_t *);
91 static int ipmi_fru_get_num_segments(section_hdl_t, door_cred_t *);
92 static int ipmi_fru_get_segments(section_hdl_t, segment_t *,
93 int, door_cred_t *);
94 static int ipmi_fru_add_segment(section_hdl_t, segment_t *,
95 section_hdl_t *, door_cred_t *);
96 static int ipmi_fru_delete_segment(segment_hdl_t, section_hdl_t *,
97 door_cred_t *);
98 static ssize_t ipmi_fru_read_segment(segment_hdl_t, void *, size_t,
99 door_cred_t *);
100 static int ipmi_fru_write_segment(segment_hdl_t, const void *, size_t,
101 segment_hdl_t *, door_cred_t *);
102 static int ipmi_fru_get_num_packets(segment_hdl_t, door_cred_t *);
103 static int ipmi_fru_get_packets(segment_hdl_t, packet_t *,
104 int, door_cred_t *);
105 static ssize_t ipmi_fru_get_payload(packet_hdl_t, void *, size_t,
106 door_cred_t *);
107 static int ipmi_fru_update_payload(packet_hdl_t, const void *, size_t,
108 packet_hdl_t *, door_cred_t *);
109 static int ipmi_fru_append_packet(segment_hdl_t, packet_t *,
110 const void *, size_t, segment_hdl_t *,
111 door_cred_t *);
112 static int ipmi_fru_delete_packet(packet_hdl_t, segment_hdl_t *, door_cred_t *);
113
114 typedef struct {
115 container_hdl_t (* open_container)(picl_nodehdl_t);
116 int (* close_container)(container_hdl_t);
117 int (* get_num_sections)(container_hdl_t, door_cred_t *);
118 int (* get_sections)(container_hdl_t, section_t *,
119 int, door_cred_t *);
120 int (* get_num_segments)(section_hdl_t, door_cred_t *);
121 int (* get_segments)(section_hdl_t, segment_t *,
122 int, door_cred_t *);
123 int (* add_segment)(section_hdl_t, segment_t *,
124 section_hdl_t *, door_cred_t *);
125 int (* delete_segment)(segment_hdl_t, section_hdl_t *,
126 door_cred_t *);
127 ssize_t (* read_segment)(segment_hdl_t, void *, size_t,
128 door_cred_t *);
129 int (* write_segment)(segment_hdl_t, const void *, size_t,
130 segment_hdl_t *, door_cred_t *);
131 int (* get_num_packets)(segment_hdl_t, door_cred_t *);
132 int (* get_packets)(segment_hdl_t, packet_t *,
133 int, door_cred_t *);
134 ssize_t (* get_payload)(packet_hdl_t, void *, size_t,
135 door_cred_t *);
136 int (* update_payload)(packet_hdl_t, const void *, size_t,
137 packet_hdl_t *, door_cred_t *);
138 int (* append_packet)(segment_hdl_t, packet_t *,
139 const void *, size_t, segment_hdl_t *,
140 door_cred_t *);
141 int (* delete_packet)(packet_hdl_t, segment_hdl_t *, door_cred_t *);
142 } fruaccess_func_ptrs_t;
143
144 static fruaccess_func_ptrs_t fruaccess_func[2] = {
145 {
146 ipmi_fru_open_container,
147 ipmi_fru_close_container,
148 ipmi_fru_get_num_sections,
149 ipmi_fru_get_sections,
150 ipmi_fru_get_num_segments,
151 ipmi_fru_get_segments,
152 ipmi_fru_add_segment,
153 ipmi_fru_delete_segment,
154 ipmi_fru_read_segment,
155 ipmi_fru_write_segment,
156 ipmi_fru_get_num_packets,
157 ipmi_fru_get_packets,
158 ipmi_fru_get_payload,
159 ipmi_fru_update_payload,
160 ipmi_fru_append_packet,
161 ipmi_fru_delete_packet,
162 },
163 {
164 sun_fru_open_container,
165 sun_fru_close_container,
166 sun_fru_get_num_sections,
167 sun_fru_get_sections,
168 sun_fru_get_num_segments,
169 sun_fru_get_segments,
170 sun_fru_add_segment,
171 sun_fru_delete_segment,
172 sun_fru_read_segment,
173 sun_fru_write_segment,
174 sun_fru_get_num_packets,
175 sun_fru_get_packets,
176 sun_fru_get_payload,
177 sun_fru_update_payload,
178 sun_fru_append_packet,
179 sun_fru_delete_packet,
180 },
181 };
182
183 static int is_valid_chassis = -1;
184 static hash_obj_t *hash_table[TABLE_SIZE];
185
186 static void
initialize_fruaccess(void)187 initialize_fruaccess(void)
188 {
189 int count;
190 for (count = 0; count < TABLE_SIZE; count++) {
191 hash_table[count] = NULL;
192 }
193
194 /* check if ipmi format has precedence */
195 if (getenv(FRUACCESS_PRECEDENCE)) {
196 precedence = IPMI_FORMAT;
197 }
198 }
199
200 /* called to lookup hash object for specified handle in the hash table. */
201 static hash_obj_t *
lookup_handle_object(handle_t handle,int object_type)202 lookup_handle_object(handle_t handle, int object_type)
203 {
204 handle_t index_to_hash;
205 hash_obj_t *first_hash_obj;
206 hash_obj_t *next_hash_obj;
207
208 index_to_hash = (handle % TABLE_SIZE);
209
210 first_hash_obj = hash_table[index_to_hash];
211 for (next_hash_obj = first_hash_obj; next_hash_obj != NULL;
212 next_hash_obj = next_hash_obj->next) {
213 if ((handle == next_hash_obj->obj_hdl) &&
214 (object_type == next_hash_obj->object_type)) {
215 return (next_hash_obj);
216 }
217 }
218 return (NULL);
219 }
220
221 /* called to allocate container hash object */
222 static hash_obj_t *
create_container_hash_object(void)223 create_container_hash_object(void)
224 {
225 hash_obj_t *hash_obj;
226 container_obj_t *cont_obj;
227
228 cont_obj = malloc(sizeof (container_obj_t));
229 if (cont_obj == NULL) {
230 return (NULL);
231 }
232
233 hash_obj = malloc(sizeof (hash_obj_t));
234 if (hash_obj == NULL) {
235 free(cont_obj);
236 return (NULL);
237 }
238
239 cont_obj->sec_obj_list = NULL;
240
241 hash_obj->object_type = CONTAINER_TYPE;
242 hash_obj->u.cont_obj = cont_obj;
243 hash_obj->next = NULL;
244 hash_obj->prev = NULL;
245
246 return (hash_obj);
247 }
248
249 /* called to allocate section hash object */
250 static hash_obj_t *
create_section_hash_object(void)251 create_section_hash_object(void)
252 {
253 hash_obj_t *hash_obj;
254 section_obj_t *sec_obj;
255
256 sec_obj = malloc(sizeof (section_obj_t));
257 if (sec_obj == NULL) {
258 return (NULL);
259 }
260
261 hash_obj = malloc(sizeof (hash_obj_t));
262 if (hash_obj == NULL) {
263 free(sec_obj);
264 return (NULL);
265 }
266
267 sec_obj->next = NULL;
268 sec_obj->seg_obj_list = NULL;
269
270 hash_obj->u.sec_obj = sec_obj;
271 hash_obj->object_type = SECTION_TYPE;
272 hash_obj->next = NULL;
273 hash_obj->prev = NULL;
274
275 return (hash_obj);
276 }
277
278 /* called to allocate segment hash object */
279 static hash_obj_t *
create_segment_hash_object(void)280 create_segment_hash_object(void)
281 {
282 hash_obj_t *hash_obj;
283 segment_obj_t *seg_obj;
284
285 seg_obj = malloc(sizeof (segment_obj_t));
286 if (seg_obj == NULL) {
287 return (NULL);
288 }
289
290 hash_obj = malloc(sizeof (hash_obj_t));
291 if (hash_obj == NULL) {
292 free(seg_obj);
293 return (NULL);
294 }
295
296 seg_obj->next = NULL;
297 seg_obj->pkt_obj_list = NULL;
298
299 hash_obj->object_type = SEGMENT_TYPE;
300 hash_obj->u.seg_obj = seg_obj;
301 hash_obj->next = NULL;
302 hash_obj->prev = NULL;
303
304 return (hash_obj);
305 }
306
307 /* called to allocate packet hash object */
308 static hash_obj_t *
create_packet_hash_object(void)309 create_packet_hash_object(void)
310 {
311 hash_obj_t *hash_obj;
312 packet_obj_t *pkt_obj;
313
314 pkt_obj = malloc(sizeof (packet_obj_t));
315 if (pkt_obj == NULL) {
316 return (NULL);
317 }
318
319 hash_obj = malloc(sizeof (hash_obj_t));
320 if (hash_obj == NULL) {
321 free(pkt_obj);
322 return (NULL);
323 }
324
325 pkt_obj->next = NULL;
326
327 hash_obj->object_type = PACKET_TYPE;
328 hash_obj->u.pkt_obj = pkt_obj;
329 hash_obj->next = NULL;
330 hash_obj->prev = NULL;
331
332 return (hash_obj);
333 }
334
335 /* called to add allocated hash object into the hash table */
336 static void
add_hashobject_to_hashtable(hash_obj_t * hash_obj,int object_type)337 add_hashobject_to_hashtable(hash_obj_t *hash_obj, int object_type)
338 {
339 handle_t index_to_hash;
340 static uint64_t handle_count = 0;
341
342 if (object_type != CONTAINER_TYPE) {
343 hash_obj->obj_hdl = ++handle_count;
344 }
345
346 /* where to add ? */
347 index_to_hash = ((hash_obj->obj_hdl) % TABLE_SIZE);
348
349 hash_obj->next = hash_table[index_to_hash];
350 hash_table[index_to_hash] = hash_obj; /* hash obj. added */
351
352 if (hash_obj->next != NULL) {
353 hash_obj->next->prev = hash_obj;
354 }
355 }
356
357 /* called to add section object list into the section list */
358 static void
add_to_sec_object_list(hash_obj_t * parent_obj,hash_obj_t * child_obj)359 add_to_sec_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj)
360 {
361 hash_obj_t *next_hash;
362
363 child_obj->u.sec_obj->cont_hdl = parent_obj->obj_hdl;
364 if (parent_obj->u.cont_obj->sec_obj_list == NULL) {
365 parent_obj->u.cont_obj->sec_obj_list = child_obj;
366 return;
367 }
368
369 for (next_hash = parent_obj->u.cont_obj->sec_obj_list;
370 next_hash->u.sec_obj->next != NULL;
371 next_hash = next_hash->u.sec_obj->next) {
372 ;
373 }
374
375 next_hash->u.sec_obj->next = child_obj;
376 }
377
378 /* called to add segment object list into segment list */
379 static void
add_to_seg_object_list(hash_obj_t * parent_obj,hash_obj_t * child_obj)380 add_to_seg_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj)
381 {
382 hash_obj_t *next_hash;
383
384 child_obj->u.seg_obj->section_hdl = parent_obj->obj_hdl;
385 if (parent_obj->u.sec_obj->seg_obj_list == NULL) {
386 parent_obj->u.sec_obj->seg_obj_list = child_obj;
387 return;
388 }
389
390 for (next_hash = parent_obj->u.sec_obj->seg_obj_list;
391 next_hash->u.seg_obj->next != NULL;
392 next_hash = next_hash->u.seg_obj->next) {
393 ;
394 }
395
396 next_hash->u.seg_obj->next = child_obj;
397 }
398
399 /* called to add packet object list into packet list */
400 static void
add_to_pkt_object_list(hash_obj_t * parent_obj,hash_obj_t * child_obj)401 add_to_pkt_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj)
402 {
403 hash_obj_t *next_hash;
404
405 /* add the packet object in the end of list */
406 child_obj->u.pkt_obj->segment_hdl = parent_obj->obj_hdl;
407
408 if (parent_obj->u.seg_obj->pkt_obj_list == NULL) {
409 parent_obj->u.seg_obj->pkt_obj_list = child_obj;
410 return;
411 }
412
413 for (next_hash = parent_obj->u.seg_obj->pkt_obj_list;
414 next_hash->u.pkt_obj->next != NULL;
415 next_hash = next_hash->u.pkt_obj->next) {
416 ;
417 }
418
419 next_hash->u.pkt_obj->next = child_obj;
420 }
421
422 /* fill the information, payload in the conatiner */
423 /*ARGSUSED*/
424 static int
initialize_ipmi_container(picl_nodehdl_t fru,hash_obj_t * cont_hash_obj)425 initialize_ipmi_container(picl_nodehdl_t fru, hash_obj_t *cont_hash_obj)
426 {
427 payload_t manr;
428 hash_obj_t *seg_hash_obj, *sec_hash_obj, *pkt_hash_obj;
429 format_t format;
430
431 format = cont_hash_obj->u.cont_obj->format;
432 /* plug to SMC driver to fetch the data */
433 if (get_manr(&format, &manr) != 0) {
434 return (-1);
435 }
436
437 cont_hash_obj->u.cont_obj->num_of_section = 1;
438 cont_hash_obj->u.cont_obj->sec_obj_list = NULL;
439
440 sec_hash_obj = create_section_hash_object();
441 if (sec_hash_obj == NULL) {
442 return (-1);
443 }
444
445 add_hashobject_to_hashtable(sec_hash_obj, SECTION_TYPE);
446
447 /* create fake section info here */
448 sec_hash_obj->u.sec_obj->num_of_segment = 1;
449 sec_hash_obj->u.sec_obj->section.handle = sec_hash_obj->obj_hdl;
450 sec_hash_obj->u.sec_obj->section.offset = 0;
451 sec_hash_obj->u.sec_obj->section.protection = READ_ONLY_SECTION;
452
453 sec_hash_obj->u.sec_obj->section.length = STATIC_LENGTH;
454 sec_hash_obj->u.sec_obj->section.version = SECTION_HDR_VER;
455 add_to_sec_object_list(cont_hash_obj, sec_hash_obj);
456
457 seg_hash_obj = create_segment_hash_object();
458 if (seg_hash_obj == NULL) {
459 return (-1);
460 }
461
462 add_hashobject_to_hashtable(seg_hash_obj, SEGMENT_TYPE);
463
464 seg_hash_obj->u.seg_obj->num_of_packets = 1;
465 seg_hash_obj->u.seg_obj->segment.handle = seg_hash_obj->obj_hdl;
466 (void) strncpy(seg_hash_obj->u.seg_obj->segment.name,
467 SD_SEGMENT_NAME,
468 sizeof (seg_hash_obj->u.seg_obj->segment.name));
469 seg_hash_obj->u.seg_obj->segment.descriptor = SD_SEGMENT_DESCRIPTOR;
470 /* tag + payload */
471 seg_hash_obj->u.seg_obj->segment.length = MANR_SIZE +
472 SEGMENT_TRAILER_LEN + SEGMENT_CHKSM_LEN;
473 add_to_seg_object_list(sec_hash_obj, seg_hash_obj);
474
475 pkt_hash_obj = create_packet_hash_object();
476 if (pkt_hash_obj == NULL) {
477 return (-1);
478 }
479 add_hashobject_to_hashtable(pkt_hash_obj, PACKET_TYPE);
480
481 pkt_hash_obj->u.pkt_obj->payload_data = manr;
482 if (mk_tag(FRU_F, 0x001, 0x0B7, &pkt_hash_obj->u.pkt_obj->tag) == 4) {
483 add_to_pkt_object_list(seg_hash_obj, pkt_hash_obj);
484 }
485 return (0);
486 }
487
488 /* Look up the container_hdl in the PICL tree. */
489 static container_hdl_t
ipmi_fru_open_container(picl_nodehdl_t fruh)490 ipmi_fru_open_container(picl_nodehdl_t fruh)
491 {
492 int err;
493 hash_obj_t *cont_hash_obj;
494
495 err = ptree_get_propval_by_name(fruh, PICL_PROP_FRUDATA_AVAIL,
496 NULL, NULL);
497 if (err != PICL_SUCCESS) {
498 return (0);
499 }
500
501 cont_hash_obj = lookup_handle_object((handle_t)fruh, CONTAINER_TYPE);
502 if (cont_hash_obj == NULL) {
503 return (0);
504 }
505
506 /* initialize the container */
507 if (initialize_ipmi_container(fruh, cont_hash_obj) != 0) {
508 return (0);
509 }
510 return (cont_hash_obj->obj_hdl);
511 }
512
513 /*ARGSUSED*/
514 static int
ipmi_fru_get_num_sections(container_hdl_t container,door_cred_t * cred)515 ipmi_fru_get_num_sections(container_hdl_t container, door_cred_t *cred)
516 {
517 hash_obj_t *cont_hash_obj;
518
519 cont_hash_obj = lookup_handle_object((handle_t)container,
520 CONTAINER_TYPE);
521 if (cont_hash_obj == NULL) {
522 return (-1);
523 }
524 return (cont_hash_obj->u.cont_obj->num_of_section);
525 }
526
527 /*ARGSUSED*/
528 static int
ipmi_fru_get_sections(container_hdl_t container,section_t * section,int max_sections,door_cred_t * cred)529 ipmi_fru_get_sections(container_hdl_t container, section_t *section,
530 int max_sections, door_cred_t *cred)
531 {
532 int count;
533 hash_obj_t *cont_object;
534 hash_obj_t *sec_hash;
535
536 cont_object = lookup_handle_object((handle_t)container,
537 CONTAINER_TYPE);
538 if (cont_object == NULL) {
539 return (-1);
540 }
541
542 if (cont_object->u.cont_obj->num_of_section > max_sections) {
543 return (-1);
544 }
545 sec_hash = cont_object->u.cont_obj->sec_obj_list;
546
547 for (count = 0; count < cont_object->u.cont_obj->num_of_section &&
548 sec_hash != NULL; count++, section++) {
549 /* populate section_t */
550 section->handle = sec_hash->u.sec_obj->section.handle;
551 section->offset = sec_hash->u.sec_obj->section.offset;
552 section->length = sec_hash->u.sec_obj->section.length;
553 section->protection = sec_hash->u.sec_obj->section.protection;
554 section->version = sec_hash->u.sec_obj->section.version;
555 sec_hash = sec_hash->u.sec_obj->next;
556 }
557 return (count);
558 }
559
560 /*ARGSUSED*/
561 static int
ipmi_fru_get_num_segments(section_hdl_t section,door_cred_t * cred)562 ipmi_fru_get_num_segments(section_hdl_t section, door_cred_t *cred)
563 {
564 hash_obj_t *sec_object;
565
566 sec_object = lookup_handle_object((handle_t)section, SECTION_TYPE);
567 if (sec_object == NULL) {
568 return (-1);
569 }
570 return (sec_object->u.sec_obj->num_of_segment);
571 }
572
573 /*ARGSUSED*/
574 static int
ipmi_fru_get_segments(section_hdl_t section,segment_t * segment,int max_segments,door_cred_t * cred)575 ipmi_fru_get_segments(section_hdl_t section, segment_t *segment,
576 int max_segments, door_cred_t *cred)
577 {
578 int count;
579 hash_obj_t *seg_hash;
580 hash_obj_t *sec_object;
581
582 sec_object = lookup_handle_object((handle_t)section, SECTION_TYPE);
583 if (sec_object == NULL) {
584 return (-1);
585 }
586
587 if (sec_object->u.sec_obj->num_of_segment > max_segments) {
588 return (-1);
589 }
590
591 seg_hash = sec_object->u.sec_obj->seg_obj_list;
592
593 for (count = 0; count < sec_object->u.sec_obj->num_of_segment &&
594 seg_hash != NULL; count++, segment++) {
595 /* populate the segment info */
596 segment->handle = seg_hash->u.seg_obj->segment.handle;
597 (void) memcpy(segment->name, seg_hash->u.seg_obj->segment.name,
598 SEG_NAME_LEN);
599 segment->descriptor = seg_hash->u.seg_obj->segment.descriptor;
600 segment->offset = seg_hash->u.seg_obj->segment.offset;
601 segment->length = seg_hash->u.seg_obj->segment.length;
602 seg_hash = seg_hash->u.seg_obj->next;
603 }
604 return (count);
605 }
606
607 /*ARGSUSED*/
608 static int
ipmi_fru_get_num_packets(segment_hdl_t segment,door_cred_t * cred)609 ipmi_fru_get_num_packets(segment_hdl_t segment, door_cred_t *cred)
610 {
611 hash_obj_t *seg_object;
612
613 seg_object = lookup_handle_object((handle_t)segment, SEGMENT_TYPE);
614 if (seg_object == NULL) {
615 return (-1);
616 }
617 return (seg_object->u.seg_obj->num_of_packets);
618 }
619
620 /*ARGSUSED*/
621 static int
ipmi_fru_get_packets(segment_hdl_t segment,packet_t * packet,int max_packets,door_cred_t * cred)622 ipmi_fru_get_packets(segment_hdl_t segment, packet_t *packet,
623 int max_packets, door_cred_t *cred)
624 {
625 int count;
626 hash_obj_t *pkt_hash;
627 hash_obj_t *seg_object;
628
629 seg_object = lookup_handle_object((handle_t)segment, SEGMENT_TYPE);
630 if (seg_object == NULL) {
631 return (-1);
632 }
633
634 if (seg_object->u.seg_obj->num_of_packets > max_packets) {
635 return (-1);
636 }
637
638 pkt_hash = seg_object->u.seg_obj->pkt_obj_list;
639
640 for (count = 0; count < seg_object->u.seg_obj->num_of_packets &&
641 pkt_hash != NULL; count++, packet++) {
642 /* populate the segment info */
643 packet->handle = pkt_hash->obj_hdl;
644 (void) memcpy(&packet->tag, &pkt_hash->u.pkt_obj->tag, 4);
645 pkt_hash = pkt_hash->u.pkt_obj->next;
646 }
647
648 return (count);
649 }
650
651 /*ARGSUSED*/
652 static ssize_t
ipmi_fru_read_segment(segment_hdl_t segment,void * buffer,size_t nbytes,door_cred_t * cred)653 ipmi_fru_read_segment(segment_hdl_t segment, void *buffer, size_t nbytes,
654 door_cred_t *cred)
655 {
656 hash_obj_t *seg_hash;
657 hash_obj_t *pkt_hash;
658
659 /* segment hash object */
660 seg_hash = lookup_handle_object(segment, SEGMENT_TYPE);
661 if (seg_hash == NULL) {
662 return (-1);
663 }
664
665 if (seg_hash->u.seg_obj->segment.length < nbytes) {
666 return (-1);
667 }
668
669 pkt_hash = seg_hash->u.seg_obj->pkt_obj_list;
670
671 if (pkt_hash == NULL) {
672 return (-1);
673 }
674
675 (void) memcpy(buffer, &pkt_hash->u.pkt_obj->payload_data,
676 sizeof (payload_t));
677 return (nbytes);
678 }
679
680 /*ARGSUSED*/
681 static ssize_t
ipmi_fru_get_payload(packet_hdl_t packet,void * buffer,size_t nbytes,door_cred_t * cred)682 ipmi_fru_get_payload(packet_hdl_t packet, void *buffer, size_t nbytes,
683 door_cred_t *cred)
684 {
685 hash_obj_t *packet_hash_obj;
686
687 /* size = size of ManR */
688 if (nbytes != MANR_SIZE) {
689 return (-1);
690 }
691
692 /* packet hash object */
693 packet_hash_obj = lookup_handle_object(packet, PACKET_TYPE);
694 if (packet_hash_obj == NULL) {
695 return (-1);
696 }
697
698 (void) memcpy(buffer, &(packet_hash_obj->u.pkt_obj->payload_data),
699 MANR_SIZE);
700 return (nbytes);
701 }
702
703 /*ARGSUSED*/
704 static int
ipmi_fru_add_segment(section_hdl_t section,segment_t * segment,section_hdl_t * newsection,door_cred_t * cred)705 ipmi_fru_add_segment(section_hdl_t section, segment_t *segment,
706 section_hdl_t *newsection, door_cred_t *cred)
707 {
708 errno = ENOTSUP;
709 return (-1);
710 }
711
712 /*ARGSUSED*/
713 static int
ipmi_fru_delete_segment(segment_hdl_t segment,section_hdl_t * newsection,door_cred_t * cred)714 ipmi_fru_delete_segment(segment_hdl_t segment,
715 section_hdl_t *newsection, door_cred_t *cred)
716 {
717 errno = ENOTSUP;
718 return (-1);
719 }
720
721
722 /*ARGSUSED*/
723 static ssize_t
ipmi_fru_write_segment(segment_hdl_t segment,const void * data,size_t nbytes,segment_hdl_t * newsegment,door_cred_t * cred)724 ipmi_fru_write_segment(segment_hdl_t segment, const void *data,
725 size_t nbytes, segment_hdl_t *newsegment, door_cred_t *cred)
726 {
727 errno = ENOTSUP;
728 return (-1);
729 }
730
731 /*ARGSUSED*/
732 static int
ipmi_fru_update_payload(packet_hdl_t packet,const void * data,size_t nbytes,packet_hdl_t * newpacket,door_cred_t * cred)733 ipmi_fru_update_payload(packet_hdl_t packet, const void *data,
734 size_t nbytes, packet_hdl_t *newpacket, door_cred_t *cred)
735 {
736 errno = ENOTSUP;
737 return (-1);
738 }
739
740 /*ARGSUSED*/
741 static int
ipmi_fru_append_packet(segment_hdl_t segment,packet_t * packet,const void * payload,size_t nbytes,segment_hdl_t * newsegment,door_cred_t * cred)742 ipmi_fru_append_packet(segment_hdl_t segment, packet_t *packet,
743 const void *payload, size_t nbytes, segment_hdl_t *newsegment,
744 door_cred_t *cred)
745 {
746 errno = ENOTSUP;
747 return (-1);
748 }
749
750 /*ARGSUSED*/
751 static int
ipmi_fru_delete_packet(packet_hdl_t packet,segment_hdl_t * newsegment,door_cred_t * cred)752 ipmi_fru_delete_packet(packet_hdl_t packet,
753 segment_hdl_t *newsegment, door_cred_t *cred)
754 {
755 errno = ENOTSUP;
756 return (-1);
757 }
758
759 static void
free_pkt_object_list(hash_obj_t * hash_obj)760 free_pkt_object_list(hash_obj_t *hash_obj)
761 {
762 hash_obj_t *next_obj;
763 hash_obj_t *free_obj;
764
765 next_obj = hash_obj->u.seg_obj->pkt_obj_list;
766 while (next_obj != NULL) {
767 free_obj = next_obj;
768 next_obj = next_obj->u.pkt_obj->next;
769 /* if prev is NULL it's the first object in the list */
770 if (free_obj->prev == NULL) {
771 hash_table[(free_obj->obj_hdl % TABLE_SIZE)] =
772 free_obj->next;
773 if (free_obj->next != NULL) {
774 free_obj->next->prev = free_obj->prev;
775 }
776 } else {
777 free_obj->prev->next = free_obj->next;
778 if (free_obj->next != NULL) {
779 free_obj->next->prev = free_obj->prev;
780 }
781 }
782
783 free(free_obj->u.pkt_obj);
784 free(free_obj);
785 }
786
787 hash_obj->u.seg_obj->pkt_obj_list = NULL;
788 }
789
790 static void
free_segment_hash(handle_t handle,hash_obj_t * sec_hash)791 free_segment_hash(handle_t handle, hash_obj_t *sec_hash)
792 {
793 hash_obj_t *seg_hash;
794 hash_obj_t *next_hash;
795
796 seg_hash = sec_hash->u.sec_obj->seg_obj_list;
797 if (seg_hash == NULL) {
798 return;
799 }
800
801 if (seg_hash->obj_hdl == handle) {
802 sec_hash->u.sec_obj->seg_obj_list = seg_hash->u.seg_obj->next;
803 } else {
804 while (seg_hash->obj_hdl != handle) {
805 next_hash = seg_hash;
806 seg_hash = seg_hash->u.seg_obj->next;
807 if (seg_hash == NULL) {
808 return;
809 }
810 }
811 next_hash->u.seg_obj->next = seg_hash->u.seg_obj->next;
812 }
813
814 if (seg_hash->prev == NULL) {
815 hash_table[(seg_hash->obj_hdl % TABLE_SIZE)] = seg_hash->next;
816 if (seg_hash->next != NULL) {
817 seg_hash->next->prev = NULL;
818 }
819 } else {
820 seg_hash->prev->next = seg_hash->next;
821 if (seg_hash->next != NULL) {
822 seg_hash->next->prev = seg_hash->prev;
823 }
824 }
825
826 free_pkt_object_list(seg_hash);
827 free(seg_hash->u.seg_obj);
828 free(seg_hash);
829 }
830
831 static int
ipmi_fru_close_container(container_hdl_t container)832 ipmi_fru_close_container(container_hdl_t container)
833 {
834 hash_obj_t *hash_obj;
835 hash_obj_t *prev_hash;
836 hash_obj_t *sec_hash_obj;
837 handle_t obj_hdl;
838
839 /* lookup for container hash object */
840 hash_obj = lookup_handle_object(container, CONTAINER_TYPE);
841 if (hash_obj == NULL) {
842 return (0);
843 }
844
845 /* points to section object list */
846 sec_hash_obj = hash_obj->u.cont_obj->sec_obj_list;
847
848 /* traverse section object list */
849 while (sec_hash_obj != NULL) {
850
851 /* traverse segment hash object in the section */
852 while (sec_hash_obj->u.sec_obj->seg_obj_list != NULL) {
853 /* object handle of the segment hash object */
854 obj_hdl =
855 sec_hash_obj->u.sec_obj->seg_obj_list->obj_hdl;
856 free_segment_hash(obj_hdl, sec_hash_obj);
857 }
858
859 /* going to free section hash object, relink the hash object */
860 if (sec_hash_obj->prev == NULL) {
861 hash_table[(sec_hash_obj->obj_hdl % TABLE_SIZE)]
862 = sec_hash_obj->next;
863 if (sec_hash_obj->next != NULL) {
864 sec_hash_obj->next->prev = NULL;
865 }
866 } else {
867 sec_hash_obj->prev->next = sec_hash_obj->next;
868 if (sec_hash_obj->next != NULL) {
869 sec_hash_obj->next->prev = sec_hash_obj->prev;
870 }
871 }
872
873 free(sec_hash_obj->u.sec_obj); /* free section hash object */
874
875 prev_hash = sec_hash_obj;
876
877 sec_hash_obj = sec_hash_obj->u.sec_obj->next;
878
879 free(prev_hash); /* free section hash */
880 }
881
882 /* free container hash object */
883 if (hash_obj->prev == NULL) {
884 hash_table[(sec_hash_obj->obj_hdl % TABLE_SIZE)] =
885 hash_obj->next;
886 if (hash_obj->next != NULL) {
887 hash_obj->next->prev = NULL;
888 }
889 } else {
890 hash_obj->prev->next = hash_obj->next;
891 if (hash_obj->next != NULL) {
892 hash_obj->next->prev = hash_obj->prev;
893 }
894 }
895
896 free(hash_obj->u.cont_obj);
897 free(hash_obj);
898 return (0);
899 }
900
901 /* opens the binary file and returns the file descriptor */
902 static int
open_file()903 open_file()
904 {
905 int fd;
906
907 if ((fd = open(INPUT_FILE, O_RDWR)) == -1) {
908 return (-1);
909 }
910 return (fd);
911 }
912
913 static void
copy_segment_layout(segment_t * seghdr,void * layout)914 copy_segment_layout(segment_t *seghdr, void *layout)
915 {
916 segment_layout_t *seg_layout;
917
918 seg_layout = (segment_layout_t *)layout;
919 (void) memcpy(seghdr->name, &seg_layout->name, SEG_NAME_LEN);
920 seghdr->descriptor = GET_SEGMENT_DESCRIPTOR;
921 seghdr->offset = seg_layout->offset;
922 seghdr->length = seg_layout->length;
923 }
924
925 static hash_obj_t *
get_container_hash_object(int object_type,handle_t handle)926 get_container_hash_object(int object_type, handle_t handle)
927 {
928 hash_obj_t *hash_obj;
929
930 switch (object_type) {
931 case CONTAINER_TYPE :
932 break;
933
934 case SECTION_TYPE :
935 hash_obj = lookup_handle_object(handle, CONTAINER_TYPE);
936 if (hash_obj == NULL) {
937 return (NULL);
938 }
939 break;
940 case SEGMENT_TYPE :
941 hash_obj = lookup_handle_object(handle, SECTION_TYPE);
942 if (hash_obj == NULL) {
943 return (NULL);
944 }
945 hash_obj = lookup_handle_object(hash_obj->u.sec_obj->cont_hdl,
946 CONTAINER_TYPE);
947 break;
948 case PACKET_TYPE :
949
950 hash_obj = lookup_handle_object(handle, SEGMENT_TYPE);
951 if (hash_obj == NULL) {
952 return (NULL);
953 }
954 hash_obj = lookup_handle_object(
955 hash_obj->u.seg_obj->section_hdl, SECTION_TYPE);
956 if (hash_obj == NULL) {
957 return (NULL);
958 }
959 hash_obj = lookup_handle_object(hash_obj->u.sec_obj->cont_hdl,
960 CONTAINER_TYPE);
961 break;
962 default :
963 return (NULL);
964 }
965 return (hash_obj);
966 }
967
968 static void
sort_offsettbl(int segcnt,seg_info_t * offset_tbl)969 sort_offsettbl(int segcnt, seg_info_t *offset_tbl)
970 {
971 int cntx;
972 int cnty;
973 seg_info_t tmp;
974
975 for (cntx = 0; cntx < segcnt+2; cntx++) {
976 for (cnty = cntx+1; cnty < segcnt + 2; cnty++) {
977 if (offset_tbl[cntx].offset >
978 offset_tbl[cnty].offset) {
979 (void) memcpy(&tmp, &offset_tbl[cnty],
980 sizeof (seg_info_t));
981 (void) memcpy(&offset_tbl[cnty],
982 &offset_tbl[cntx],
983 sizeof (seg_info_t));
984
985 (void) memcpy(&offset_tbl[cntx], &tmp,
986 sizeof (seg_info_t));
987 }
988 }
989 }
990 }
991
992 /*
993 * Description : move_segment_data() reads the segment data and writes it
994 * back to the new segment offset.
995 */
996
997 static void
move_segment_data(void * seghdr,int newoffset,container_hdl_t contfd)998 move_segment_data(void *seghdr, int newoffset, container_hdl_t contfd)
999 {
1000 int ret;
1001 char *buffer;
1002 segment_layout_t *segment;
1003 format_t format;
1004 hash_obj_t *cont_hash;
1005
1006 segment = (segment_layout_t *)seghdr;
1007
1008 buffer = alloca(segment->length);
1009 if (buffer == NULL) {
1010 return;
1011 }
1012
1013 cont_hash = lookup_handle_object((handle_t)contfd, CONTAINER_TYPE);
1014 if (cont_hash == NULL) {
1015 return;
1016 }
1017
1018 format = cont_hash->u.cont_obj->format;
1019
1020 ret = pread_new(contfd, buffer,
1021 segment->length, segment->offset, &format);
1022 if (ret != segment->length) {
1023 return;
1024 }
1025
1026 segment->offset = newoffset;
1027
1028 ret = pwrite_new(contfd, buffer, segment->length, segment->offset,
1029 &format);
1030 if (ret != segment->length) {
1031 return;
1032 }
1033 }
1034
1035 /*
1036 * Description : pack_segment_data() moves the segment data if there is
1037 * a hole between two segments.
1038 */
1039
1040 static void
pack_segment_data(char * seghdr,int segcnt,container_hdl_t contfd,seg_info_t * offset_tbl)1041 pack_segment_data(char *seghdr, int segcnt, container_hdl_t contfd,
1042 seg_info_t *offset_tbl)
1043 {
1044 int cnt;
1045 int diff;
1046 int newoffset;
1047
1048 for (cnt = segcnt + 1; cnt > 0; cnt--) {
1049 if (!offset_tbl[cnt - 1].fixed) {
1050 if (offset_tbl[cnt].offset
1051 - (offset_tbl[cnt -1 ].offset
1052 + offset_tbl[cnt - 1].length) > 0) {
1053
1054 diff = offset_tbl[cnt].offset -
1055 (offset_tbl[cnt - 1].offset
1056 + offset_tbl[cnt - 1].length);
1057 newoffset = offset_tbl[cnt - 1].offset
1058 + diff;
1059
1060 move_segment_data(seghdr, newoffset,
1061 contfd);
1062
1063 offset_tbl[cnt - 1].offset = newoffset;
1064
1065 sort_offsettbl(segcnt, offset_tbl);
1066 }
1067 }
1068 }
1069 }
1070
1071 /*
1072 * Description : build_offset_tbl() builds the offset table by reading all the
1073 * segment header. it makes two more entry into the table one for
1074 * section size and another with start of the section after the
1075 * segment header.
1076 */
1077
1078 static int
build_offset_tbl(void * seghdr,int segcnt,int secsize,seg_info_t * offset_tbl)1079 build_offset_tbl(void *seghdr, int segcnt, int secsize,
1080 seg_info_t *offset_tbl)
1081 {
1082 int cnt;
1083 fru_segdesc_t segdesc;
1084 segment_layout_t *segment;
1085
1086 for (cnt = 0; cnt < segcnt; cnt++) {
1087 segment = (segment_layout_t *)(seghdr) + cnt;
1088
1089 (void) memcpy(&segdesc, &segment->descriptor,
1090 sizeof (uint32_t));
1091 offset_tbl[cnt].segnum = cnt;
1092 offset_tbl[cnt].offset = segment->offset;
1093 offset_tbl[cnt].length = segment->length;
1094 offset_tbl[cnt].fixed = segdesc.field.fixed;
1095 }
1096
1097 /* upper boundary of segment area (lower address bytes) */
1098 offset_tbl[cnt].segnum = -1;
1099 offset_tbl[cnt].offset = sizeof (section_layout_t) + ((cnt + 1)
1100 * sizeof (segment_layout_t));
1101
1102 offset_tbl[cnt].length = 0;
1103 offset_tbl[cnt].fixed = 1;
1104 /* lower boundary of segment area (higher address bytes) */
1105
1106 offset_tbl[cnt+1].segnum = -1;
1107 offset_tbl[cnt+1].offset = secsize;
1108 offset_tbl[cnt+1].length = 0;
1109 offset_tbl[cnt+1].fixed = 1;
1110 return (0);
1111 }
1112
1113 static int
hole_discovery(int bytes,int segcnt,int * totsize,seg_info_t * offset_tbl)1114 hole_discovery(int bytes, int segcnt, int *totsize, seg_info_t *offset_tbl)
1115 {
1116 int cnt = 0;
1117
1118 *totsize = 0;
1119 for (cnt = segcnt + 1; cnt > 0; cnt--) {
1120 if (bytes <= offset_tbl[cnt].offset -
1121 (offset_tbl[cnt - 1].offset +
1122 offset_tbl[cnt - 1].length)) {
1123 return (offset_tbl[cnt].offset - bytes);
1124 }
1125
1126 *totsize += offset_tbl[cnt].offset -
1127 (offset_tbl[cnt - 1].offset +
1128 offset_tbl[cnt - 1].length);
1129 }
1130 return (0);
1131 }
1132
1133
1134 /*
1135 * Description : segment_hdr_present() verify space for new segment header to
1136 * be added.
1137 */
1138
1139 static int
segment_hdr_present(int segoffset,int size,seg_info_t * offset_tbl)1140 segment_hdr_present(int segoffset, int size, seg_info_t *offset_tbl)
1141 {
1142 if ((segoffset + size) <= offset_tbl[0].offset)
1143 return (0);
1144 else
1145 return (-1);
1146 }
1147
1148 /*
1149 * Description : find_offset() is called from fru_add_segment routine to find
1150 * a valid offset.
1151 */
1152
1153 static int
find_offset(char * seghdr,int segcnt,int secsize,int * sectionoffset,int segsize,int fix,container_hdl_t contfd)1154 find_offset(char *seghdr, int segcnt, int secsize, int *sectionoffset,
1155 int segsize, int fix, container_hdl_t contfd)
1156 {
1157 int ret;
1158 int newoffset;
1159 int totsize = 0;
1160 seg_info_t *offset_tbl;
1161
1162 if (segcnt == 0) {
1163 if (!fix) { /* if not fixed segment */
1164 *sectionoffset = secsize - segsize;
1165 }
1166 return (0);
1167 }
1168
1169 /*
1170 * two extra segment info structure are allocated for start of segment
1171 * and other end of segment. first segment offset is first available
1172 * space and length is 0. second segment offset is is segment length and
1173 * offset is 0. build_offset_tbl() explains how upper boundary and lower
1174 * boudary segment area are initialized in seg_info_t table.
1175 */
1176
1177 offset_tbl = malloc((segcnt + 2) * sizeof (seg_info_t));
1178 if (offset_tbl == NULL) {
1179 return (-1);
1180 }
1181
1182 /* read all the segment header to make offset table */
1183 ret = build_offset_tbl(seghdr, segcnt, secsize, offset_tbl);
1184 if (ret != 0) {
1185 free(offset_tbl);
1186 return (-1);
1187 }
1188
1189 /* sort the table */
1190 sort_offsettbl(segcnt, offset_tbl);
1191
1192 /* new segment header offset */
1193 newoffset = sizeof (section_layout_t) + segcnt *
1194 sizeof (segment_layout_t);
1195
1196 /* do? new segment header overlap any existing data */
1197 ret = segment_hdr_present(newoffset, sizeof (segment_layout_t),
1198 offset_tbl);
1199 if (ret != 0) { /* make room for new segment if possible */
1200
1201 /* look for hole in order to move segment data */
1202 if (offset_tbl[0].fixed == SEGMENT_FIXED) { /* fixed segment */
1203 free(offset_tbl);
1204 return (-1);
1205 }
1206
1207 newoffset = hole_discovery(offset_tbl[0].length,
1208 segcnt, &totsize, offset_tbl);
1209 if (newoffset != 0) { /* found new offset */
1210 /* now new offset */
1211 offset_tbl[0].offset = newoffset;
1212
1213 /* move the segment data */
1214 move_segment_data(seghdr, newoffset, contfd);
1215 /* again sort the offset table */
1216 sort_offsettbl(segcnt, offset_tbl);
1217 } else {
1218 /* pack the existing hole */
1219 if (totsize > offset_tbl[0].length) {
1220 pack_segment_data(seghdr, segcnt,
1221 contfd, offset_tbl);
1222 } else {
1223 free(offset_tbl);
1224 return (-1);
1225 }
1226 }
1227 }
1228
1229 totsize = 0;
1230 newoffset = hole_discovery(segsize, segcnt, &totsize, offset_tbl);
1231
1232 if (newoffset == 0) { /* No hole found */
1233 if (totsize >= segsize) {
1234 pack_segment_data(seghdr, segcnt, contfd,
1235 offset_tbl);
1236 newoffset = hole_discovery(segsize, segcnt,
1237 &totsize, offset_tbl);
1238 if (newoffset != 0) {
1239 *sectionoffset = newoffset;
1240 free(offset_tbl);
1241 return (0);
1242 }
1243 }
1244 } else {
1245 *sectionoffset = newoffset;
1246 free(offset_tbl);
1247 return (0);
1248 }
1249 free(offset_tbl);
1250 return (-1);
1251 }
1252
1253 /*
1254 * Description :sun_fru_open_container() opens the container associated with
1255 * a fru. it's called by data plugin module before creating
1256 * container property. it calls picltree library routine to get
1257 * the device path and driver binding name for the fru to get the
1258 * corresponding fru name that describe the fru layout.
1259 *
1260 * Arguments :picl_hdl_t fru
1261 * A handle for PICL tree node of class "fru" representing the
1262 * FRU with the container to open.
1263 *
1264 * Return :
1265 * On Success, a Positive integer container handle. is returned
1266 * for use in subsequent fru operations;on error, 0 is returned
1267 * and "errno" is set appropriately.
1268 */
1269 static container_hdl_t
sun_fru_open_container(picl_nodehdl_t fruhdl)1270 sun_fru_open_container(picl_nodehdl_t fruhdl)
1271 {
1272 int count;
1273 hash_obj_t *cont_hash_obj;
1274 hash_obj_t *sec_hash_obj;
1275
1276 cont_hash_obj = lookup_handle_object((handle_t)fruhdl, CONTAINER_TYPE);
1277 if (cont_hash_obj == NULL) {
1278 return (NULL);
1279 }
1280
1281 cont_hash_obj->u.cont_obj->num_of_section = NUM_OF_SECTIONS;
1282 cont_hash_obj->u.cont_obj->sec_obj_list = NULL;
1283
1284 for (count = 0; count < NUM_OF_SECTIONS; count++) {
1285 sec_hash_obj = create_section_hash_object();
1286 if (sec_hash_obj == NULL) {
1287 return (NULL);
1288 }
1289
1290 add_hashobject_to_hashtable(sec_hash_obj, SECTION_TYPE);
1291
1292 if (count == 0) {
1293 sec_hash_obj->u.sec_obj->section.offset =
1294 DYNAMIC_OFFSET;
1295 sec_hash_obj->u.sec_obj->section.protection =
1296 WRITE_SECTION;
1297 sec_hash_obj->u.sec_obj->section.length =
1298 DYNAMIC_LENGTH;
1299 } else {
1300 sec_hash_obj->u.sec_obj->section.offset = STATIC_OFFSET;
1301 sec_hash_obj->u.sec_obj->section.protection =
1302 READ_ONLY_SECTION;
1303 sec_hash_obj->u.sec_obj->section.length = STATIC_LENGTH;
1304 }
1305
1306 sec_hash_obj->u.sec_obj->section.version = SECTION_HDR_VER;
1307
1308 add_to_sec_object_list(cont_hash_obj, sec_hash_obj);
1309 }
1310
1311 return (cont_hash_obj->obj_hdl);
1312 }
1313
1314 static int
verify_header_crc8(headerrev_t head_ver,unsigned char * bytes,int length)1315 verify_header_crc8(headerrev_t head_ver, unsigned char *bytes, int length)
1316 {
1317 int crc_offset = 0;
1318 unsigned char orig_crc8 = 0;
1319 unsigned char calc_crc8 = 0;
1320
1321 switch (head_ver) {
1322 case SECTION_HDR_VER:
1323 crc_offset = 4;
1324 break;
1325 default:
1326 errno = EINVAL;
1327 return (0);
1328 }
1329
1330 orig_crc8 = bytes[crc_offset];
1331 bytes[crc_offset] = 0x00; /* clear for calc */
1332 calc_crc8 = compute_crc8(bytes, length);
1333 bytes[crc_offset] = orig_crc8; /* restore */
1334
1335 return (orig_crc8 == calc_crc8);
1336 }
1337
1338 /*
1339 * Description :
1340 * sun_fru_get_num_sections() returns number of sections in a
1341 * container. it calls get_container_index() to get the container
1342 * index number in the container list.
1343 *
1344 * Arguments :
1345 * container_hdl_t : container handle.
1346 *
1347 * Return :
1348 * int
1349 * On success, returns number of sections in a container.
1350 *
1351 */
1352 /*ARGSUSED*/
1353 static int
sun_fru_get_num_sections(container_hdl_t container,door_cred_t * cred)1354 sun_fru_get_num_sections(container_hdl_t container, door_cred_t *cred)
1355 {
1356 hash_obj_t *hash_object;
1357
1358 hash_object = lookup_handle_object(container, CONTAINER_TYPE);
1359 if (hash_object == NULL) {
1360 return (-1);
1361 }
1362
1363 return (hash_object->u.cont_obj->num_of_section);
1364 }
1365
1366 /*
1367 * called from fru_get_sections()
1368 */
1369
1370 static void
get_section(int fd,hash_obj_t * sec_hash,section_t * section)1371 get_section(int fd, hash_obj_t *sec_hash, section_t *section)
1372 {
1373 int retval;
1374 int size;
1375 int count;
1376 uint16_t hdrver;
1377 hash_obj_t *seg_hash;
1378 unsigned char *buffer;
1379 section_obj_t *sec_obj;
1380 section_layout_t sec_hdr;
1381 segment_layout_t *seg_hdr;
1382 segment_layout_t *seg_buf;
1383 format_t format;
1384 hash_obj_t *cont_hash;
1385
1386 sec_obj = sec_hash->u.sec_obj;
1387 if (sec_obj == NULL) {
1388 return;
1389 }
1390
1391 /* populate section_t */
1392 section->handle = sec_hash->obj_hdl;
1393 section->offset = sec_obj->section.offset;
1394 section->length = sec_obj->section.length;
1395 section->protection = sec_obj->section.protection;
1396 section->version = sec_obj->section.version;
1397 sec_obj->num_of_segment = 0;
1398
1399 cont_hash = get_container_hash_object(SEGMENT_TYPE, sec_hash->obj_hdl);
1400 if (cont_hash == NULL) {
1401 return;
1402 }
1403
1404 format = cont_hash->u.cont_obj->format;
1405
1406 /* read section header layout */
1407 retval = pread_new(fd, &sec_hdr, sizeof (sec_hdr),
1408 sec_obj->section.offset, &format);
1409 if (retval != sizeof (sec_hdr)) {
1410 return;
1411 }
1412
1413 hdrver = GET_SECTION_HDR_VERSION;
1414
1415 if ((sec_hdr.headertag != SECTION_HDR_TAG) &&
1416 (hdrver != section->version)) {
1417 return;
1418 }
1419
1420 /* size = section layout + total sizeof segment header */
1421 size = sizeof (sec_hdr) + ((sec_hdr.segmentcount)
1422 * sizeof (segment_layout_t));
1423 buffer = alloca(size);
1424 if (buffer == NULL) {
1425 return;
1426 }
1427
1428 /* segment header buffer */
1429 seg_buf = alloca(size - sizeof (sec_hdr));
1430 if (seg_buf == NULL) {
1431 return;
1432 }
1433
1434 /* read segment header */
1435 retval = pread_new(fd, seg_buf, size - sizeof (sec_hdr),
1436 sec_obj->section.offset + sizeof (sec_hdr), &format);
1437 if (retval != (size - sizeof (sec_hdr))) {
1438 return;
1439 }
1440
1441 /* copy section header layout */
1442 (void) memcpy(buffer, &sec_hdr, sizeof (sec_hdr));
1443
1444 /* copy segment header layout */
1445 (void) memcpy(buffer + sizeof (sec_hdr), seg_buf, size -
1446 sizeof (sec_hdr));
1447
1448 /* verify crc8 */
1449 retval = verify_header_crc8(hdrver, buffer, size);
1450 if (retval != TRUE) {
1451 return;
1452 }
1453
1454 section->version = hdrver;
1455 sec_obj->section.version = hdrver;
1456
1457 seg_hdr = (segment_layout_t *)seg_buf;
1458
1459 for (count = 0; count < sec_hdr.segmentcount; count++, seg_hdr++) {
1460 seg_hash = create_segment_hash_object();
1461 if (seg_hash == NULL) {
1462 return;
1463 }
1464
1465 add_hashobject_to_hashtable(seg_hash, SEGMENT_TYPE);
1466
1467 copy_segment_layout(&seg_hash->u.seg_obj->segment, seg_hdr);
1468
1469 add_to_seg_object_list(sec_hash, seg_hash);
1470
1471 sec_obj->num_of_segment++;
1472 }
1473 }
1474
1475 /*
1476 * Description :
1477 * sun_fru_get_sections() fills an array of section structures
1478 * passed as an argument.
1479 *
1480 * Arguments :
1481 * container_hdl_t : container handle(device descriptor).
1482 * section_t : array of section structure.
1483 * int : maximum number of section in a container.
1484 *
1485 * Returns :
1486 * int
1487 * On success,the number of section structures written is returned;
1488 * on error, -1 is returned and "errno" is set appropriately.
1489 *
1490 */
1491 /*ARGSUSED*/
1492 static int
sun_fru_get_sections(container_hdl_t container,section_t * section,int maxsec,door_cred_t * cred)1493 sun_fru_get_sections(container_hdl_t container, section_t *section, int maxsec,
1494 door_cred_t *cred)
1495 {
1496 int device_fd;
1497 int count;
1498 hash_obj_t *cont_object;
1499 hash_obj_t *sec_hash;
1500
1501 cont_object = lookup_handle_object(container, CONTAINER_TYPE);
1502 if (cont_object == NULL) {
1503 return (-1);
1504 }
1505
1506 if (cont_object->u.cont_obj->num_of_section > maxsec) {
1507 return (-1);
1508 }
1509
1510 sec_hash = cont_object->u.cont_obj->sec_obj_list;
1511 if (sec_hash == NULL) {
1512 return (-1);
1513 }
1514
1515 device_fd = open_file();
1516
1517 if (device_fd < 0) {
1518 return (-1);
1519 }
1520
1521 for (count = 0; count < cont_object->u.cont_obj->num_of_section;
1522 count++, section++) {
1523 section->version = -1;
1524 /* populate section_t */
1525 get_section(device_fd, sec_hash, section);
1526 sec_hash = sec_hash->u.sec_obj->next;
1527 }
1528
1529 (void) close(device_fd);
1530
1531 return (count);
1532 }
1533
1534 /*
1535 * Description :
1536 * sun_fru_get_num_segments() returns the current number of
1537 * segments in a section.
1538 *
1539 * Arguments :
1540 * section_hdl_t : section header holding section information.
1541 *
1542 * Return :
1543 * int
1544 * On success, the number of segments in the argument section is
1545 * returned; on error -1 is returned.
1546 */
1547 /*ARGSUSED*/
1548 static int
sun_fru_get_num_segments(section_hdl_t section,door_cred_t * cred)1549 sun_fru_get_num_segments(section_hdl_t section, door_cred_t *cred)
1550 {
1551 hash_obj_t *sec_object;
1552 section_obj_t *sec_obj;
1553
1554 sec_object = lookup_handle_object(section, SECTION_TYPE);
1555 if (sec_object == NULL) {
1556 return (-1);
1557 }
1558
1559 sec_obj = sec_object->u.sec_obj;
1560 if (sec_obj == NULL) {
1561 return (-1);
1562 }
1563
1564 return (sec_obj->num_of_segment);
1565 }
1566
1567 /*
1568 * Description :
1569 * sun_fru_get_segments() fills an array of structures
1570 * representing the segments in a section.
1571 *
1572 * Arguments :
1573 * section_hdl_t : holds section number.
1574 * segment_t : on success will hold segment information.
1575 * int : maximum number of segment.
1576 *
1577 * Return :
1578 * int
1579 * On success, the number of segment structures written is
1580 * returned; on errno -1 is returned.
1581 */
1582 /* ARGSUSED */
1583 static int
sun_fru_get_segments(section_hdl_t section,segment_t * segment,int maxseg,door_cred_t * cred)1584 sun_fru_get_segments(section_hdl_t section, segment_t *segment, int maxseg,
1585 door_cred_t *cred)
1586 {
1587 int count;
1588 hash_obj_t *sec_object;
1589 hash_obj_t *seg_object;
1590 section_obj_t *sec_obj;
1591
1592 sec_object = lookup_handle_object(section, SECTION_TYPE);
1593 if (sec_object == NULL) {
1594 return (-1);
1595 }
1596
1597 sec_obj = sec_object->u.sec_obj;
1598 if (sec_obj == NULL) {
1599 return (-1);
1600 }
1601
1602 if (sec_obj->num_of_segment > maxseg) {
1603 return (-1);
1604 }
1605
1606 seg_object = sec_object->u.sec_obj->seg_obj_list;
1607 if (seg_object == NULL) {
1608 return (-1);
1609 }
1610
1611 for (count = 0; count < sec_obj->num_of_segment; count++) {
1612
1613 /* populate segment_t */
1614 segment->handle = seg_object->obj_hdl;
1615 (void) memcpy(segment->name,
1616 seg_object->u.seg_obj->segment.name, SEG_NAME_LEN);
1617 segment->descriptor = seg_object->u.seg_obj->segment.descriptor;
1618 segment->offset = seg_object->u.seg_obj->segment.offset;
1619 segment->length = seg_object->u.seg_obj->segment.length;
1620 seg_object = seg_object->u.seg_obj->next;
1621 segment++;
1622 }
1623 return (0);
1624 }
1625
1626 /*
1627 * Description :
1628 * sun_fru_add_segment() adds a segment to a section.
1629 *
1630 * Arguments :
1631 * section_hdl_t section
1632 * A handle for the section in which to add the segment.
1633 *
1634 * segment_t *segment
1635 * On entry, the "handle" component of "segment" is ignored and the
1636 * remaining components specify the parameters of the segment to be
1637 * added. On return, the "handle" component is set to the handle
1638 * for the added segment. The segment offset is mandatory for FIXED
1639 * segments; otherwise, the offset is advisory.
1640 *
1641 * Return :
1642 * int
1643 * On success, 0 is returned; on error -1 is returned.
1644 *
1645 */
1646 static int
sun_fru_add_segment(section_hdl_t section,segment_t * segment,section_hdl_t * newsection,door_cred_t * cred)1647 sun_fru_add_segment(section_hdl_t section, segment_t *segment,
1648 section_hdl_t *newsection, door_cred_t *cred)
1649 {
1650 int fd;
1651 int retval;
1652 int offset;
1653 int sec_size;
1654 int seg_cnt;
1655 int bufsize;
1656 int new_seg_offset;
1657 int new_seg_length;
1658 int fixed_segment;
1659 char trailer[] = { 0x0c, 0x00, 0x00, 0x00, 0x00 };
1660 hash_obj_t *cont_hash;
1661 hash_obj_t *sec_hash;
1662 hash_obj_t *seg_hash;
1663 fru_segdesc_t *new_seg_desc;
1664 unsigned char *crcbuf;
1665 section_layout_t sec_layout;
1666 segment_layout_t *seg_layout;
1667 segment_layout_t *segment_buf;
1668 format_t format;
1669
1670 /* check the effective uid of the client */
1671 if (cred->dc_euid != 0) {
1672 errno = EPERM;
1673 return (-1); /* not a root */
1674 }
1675
1676 /* section hash */
1677 sec_hash = lookup_handle_object(section, SECTION_TYPE);
1678 if (sec_hash == NULL) {
1679 return (-1);
1680 }
1681
1682 /* check for read-only section */
1683 if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) {
1684 errno = EPERM;
1685 return (-1);
1686 }
1687
1688 /* look for duplicate segment */
1689 seg_hash = sec_hash->u.sec_obj->seg_obj_list;
1690 while (seg_hash != NULL) {
1691 if (strncmp(segment->name, seg_hash->u.seg_obj->segment.name,
1692 SEG_NAME_LEN) == 0) {
1693 errno = EEXIST;
1694 return (-1); /* can't add duplicate segment */
1695 }
1696 seg_hash = seg_hash->u.seg_obj->next;
1697 }
1698
1699 /* get the container hash */
1700 cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl,
1701 CONTAINER_TYPE);
1702 if (cont_hash == NULL) {
1703 return (-1);
1704 }
1705
1706 format = cont_hash->u.cont_obj->format;
1707
1708 /* open the container */
1709 fd = open_file();
1710 if (fd < 0) {
1711 return (-1);
1712 }
1713
1714 /* section start here */
1715 offset = sec_hash->u.sec_obj->section.offset;
1716
1717 /* read section header layout */
1718 retval = pread_new(fd, &sec_layout, sizeof (sec_layout), offset,
1719 &format);
1720 if (retval != sizeof (sec_layout)) {
1721 (void) close(fd);
1722 return (-1);
1723 }
1724
1725 /* check for valid section header */
1726 if (sec_layout.headertag != SECTION_HDR_TAG) {
1727 /* write a new one */
1728 sec_layout.headertag = SECTION_HDR_TAG;
1729 sec_layout.headerversion[0] = SECTION_HDR_VER_BIT0;
1730 sec_layout.headerversion[1] = SECTION_HDR_VER_BIT1;
1731 sec_layout.headerlength = sizeof (sec_layout);
1732 sec_layout.segmentcount = 0;
1733 }
1734
1735 /* section size */
1736 sec_size = sec_hash->u.sec_obj->section.length;
1737
1738 /* number of segment in the section */
1739 seg_cnt = sec_layout.segmentcount;
1740
1741 /* total sizeof segment + new segment */
1742 bufsize = sizeof (segment_layout_t) * (seg_cnt + 1);
1743 segment_buf = alloca(bufsize);
1744 if (segment_buf == NULL) {
1745 return (-1);
1746 }
1747
1748 /* read entire segment header */
1749 retval = pread_new(fd, segment_buf,
1750 (bufsize - sizeof (segment_layout_t)),
1751 offset + sizeof (section_layout_t), &format);
1752 if (retval != (bufsize - sizeof (segment_layout_t))) {
1753 (void) close(fd);
1754 return (-1);
1755 }
1756
1757 new_seg_offset = segment->offset; /* new segment offset */
1758 new_seg_length = segment->length; /* new segment length */
1759
1760 new_seg_desc = (fru_segdesc_t *)&segment->descriptor;
1761
1762 fixed_segment = new_seg_desc->field.fixed;
1763
1764 /* get new offset for new segment to be addedd */
1765 retval = find_offset((char *)segment_buf, seg_cnt, sec_size,
1766 &new_seg_offset, new_seg_length, fixed_segment, fd);
1767
1768 if (retval != 0) {
1769 (void) close(fd);
1770 errno = EAGAIN;
1771 return (-1);
1772 }
1773
1774 /* copy new segment data in segment layout */
1775 seg_layout = (segment_layout_t *)(segment_buf + seg_cnt);
1776 (void) memcpy(&seg_layout->name, segment->name, SEG_NAME_LEN);
1777 (void) memcpy(seg_layout->descriptor, &segment->descriptor,
1778 sizeof (uint32_t));
1779 seg_layout->length = segment->length;
1780 seg_layout->offset = new_seg_offset; /* new segment offset */
1781
1782 sec_layout.segmentcount += 1;
1783
1784 crcbuf = alloca(sizeof (section_layout_t) + bufsize);
1785 if (crcbuf == NULL) {
1786 (void) close(fd);
1787 return (-1);
1788 }
1789
1790 sec_layout.headercrc8 = 0;
1791 sec_layout.headerlength += sizeof (segment_layout_t);
1792
1793 (void) memcpy(crcbuf, (char *)&sec_layout, sizeof (section_layout_t));
1794 (void) memcpy(crcbuf + sizeof (section_layout_t), segment_buf, bufsize);
1795
1796 sec_layout.headercrc8 = compute_crc8(crcbuf, bufsize +
1797 sizeof (section_layout_t));
1798
1799 /* write section header */
1800 retval = pwrite_new(fd, &sec_layout, sizeof (section_layout_t),
1801 offset, &format);
1802 if (retval != sizeof (section_layout_t)) {
1803 (void) close(fd);
1804 return (-1);
1805 }
1806
1807 /* write segment header */
1808 retval = pwrite_new(fd, segment_buf, bufsize, offset +
1809 sizeof (section_layout_t), &format);
1810 if (retval != bufsize) {
1811 (void) close(fd);
1812 return (-1);
1813 }
1814
1815 /* write segment trailer */
1816 retval = pwrite_new(fd, &trailer, sizeof (trailer), new_seg_offset,
1817 &format);
1818 if (retval != sizeof (trailer)) {
1819 (void) close(fd);
1820 return (-1);
1821 }
1822
1823 (void) close(fd);
1824
1825 /* create new segment hash object */
1826 seg_hash = create_segment_hash_object();
1827 if (seg_hash == NULL) {
1828 return (-1);
1829 }
1830
1831 add_hashobject_to_hashtable(seg_hash, SEGMENT_TYPE);
1832
1833 copy_segment_layout(&seg_hash->u.seg_obj->segment, seg_layout);
1834
1835 add_to_seg_object_list(sec_hash, seg_hash);
1836
1837 sec_hash->u.sec_obj->num_of_segment += 1;
1838 seg_hash->u.seg_obj->trailer_offset = new_seg_offset;
1839 *newsection = section; /* return the new section handle */
1840 return (0);
1841 }
1842
1843 /*
1844 * Description :
1845 * sun_fru_delete_segment() deletes a segment from a section; the
1846 * associated container data is not altered.
1847 *
1848 * Arguments : segment_hdl_t segment handle.
1849 * section_hdl_t new section handle.
1850 *
1851 * Return :
1852 * int
1853 * On success, 0 returned; On error -1 is returned.
1854 */
1855 static int
sun_fru_delete_segment(segment_hdl_t segment,section_hdl_t * newsection,door_cred_t * cred)1856 sun_fru_delete_segment(segment_hdl_t segment, section_hdl_t *newsection,
1857 door_cred_t *cred)
1858 {
1859 int num_of_seg;
1860 int bufsize;
1861 int count;
1862 int retval;
1863 int fd;
1864 int segnum;
1865 hash_obj_t *seg_hash;
1866 hash_obj_t *sec_hash;
1867 hash_obj_t *cont_hash;
1868 hash_obj_t *tmp_hash;
1869 unsigned char *buffer;
1870 fru_segdesc_t *desc;
1871 segment_layout_t *seg_buf;
1872 section_layout_t *sec_layout;
1873 segment_layout_t *seg_layout;
1874 segment_layout_t *next_layout;
1875 format_t format;
1876
1877 /* check the effective uid of the client */
1878 if (cred->dc_euid != 0) {
1879 errno = EPERM;
1880 return (-1); /* not a root */
1881 }
1882
1883 seg_hash = lookup_handle_object(segment, SEGMENT_TYPE);
1884 if (seg_hash == NULL) {
1885 return (-1);
1886 }
1887
1888 desc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor;
1889 if (!(desc->field.field_perm & SEGMENT_DELETE)) {
1890 errno = EPERM;
1891 return (-1); /* can't delete this segment */
1892 }
1893
1894 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
1895 SECTION_TYPE);
1896 if (sec_hash == NULL) {
1897 return (-1);
1898 }
1899
1900 if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) {
1901 errno = EPERM;
1902 return (-1);
1903 }
1904
1905 num_of_seg = sec_hash->u.sec_obj->num_of_segment;
1906
1907 bufsize = (sizeof (segment_layout_t) * num_of_seg);
1908
1909 seg_buf = alloca(bufsize);
1910 if (seg_buf == NULL) {
1911 return (-1);
1912 }
1913
1914 segnum = 0;
1915 for (tmp_hash = sec_hash->u.sec_obj->seg_obj_list; tmp_hash != NULL;
1916 tmp_hash = tmp_hash->u.seg_obj->next) {
1917 if (tmp_hash->obj_hdl == segment) {
1918 break;
1919 }
1920 segnum++;
1921 }
1922
1923 cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl,
1924 CONTAINER_TYPE);
1925 if (cont_hash == NULL) {
1926 return (-1);
1927 }
1928 format = cont_hash->u.cont_obj->format;
1929
1930 fd = open_file();
1931 if (fd < 0) {
1932 return (-1);
1933 }
1934
1935 sec_layout = alloca(sizeof (section_layout_t));
1936 if (sec_layout == NULL) {
1937 (void) close(fd);
1938 return (-1);
1939 }
1940
1941 /* read section layout header */
1942 retval = pread_new(fd, sec_layout, sizeof (section_layout_t),
1943 sec_hash->u.sec_obj->section.offset, &format);
1944 if (retval != sizeof (section_layout_t)) {
1945 (void) close(fd);
1946 return (-1);
1947 }
1948
1949 /* read segment header layout */
1950 retval = pread_new(fd, seg_buf, bufsize,
1951 sec_hash->u.sec_obj->section.offset +
1952 sizeof (section_layout_t), &format);
1953 if (retval != bufsize) {
1954 (void) close(fd);
1955 return (-1);
1956 }
1957
1958 seg_layout = (segment_layout_t *)(seg_buf + segnum);
1959 next_layout = seg_layout;
1960 for (count = segnum; count < sec_hash->u.sec_obj->num_of_segment-1;
1961 count++) {
1962 next_layout++;
1963 (void) memcpy(seg_layout, next_layout,
1964 sizeof (segment_layout_t));
1965 seg_layout++;
1966 }
1967
1968 (void) memset(seg_layout, '\0', sizeof (segment_layout_t));
1969
1970 sec_layout->headercrc8 = 0;
1971
1972 sec_layout->headerlength -= sizeof (segment_layout_t);
1973 sec_layout->segmentcount -= 1;
1974
1975 buffer = alloca(sec_layout->headerlength);
1976 if (buffer == NULL) {
1977 (void) close(fd);
1978 return (-1);
1979 }
1980
1981 (void) memcpy(buffer, sec_layout, sizeof (section_layout_t));
1982 (void) memcpy(buffer + sizeof (section_layout_t), seg_buf, bufsize
1983 - sizeof (segment_layout_t));
1984 sec_layout->headercrc8 = compute_crc8(buffer,
1985 sec_layout->headerlength);
1986
1987 /* write section header with update crc8 and header length */
1988 retval = pwrite_new(fd, sec_layout, sizeof (section_layout_t),
1989 sec_hash->u.sec_obj->section.offset, &format);
1990 if (retval != sizeof (section_layout_t)) {
1991 (void) close(fd);
1992 return (-1);
1993 }
1994
1995 /* write the update segment header */
1996 retval = pwrite_new(fd, seg_buf, bufsize,
1997 sec_hash->u.sec_obj->section.offset +
1998 sizeof (section_layout_t), &format);
1999 (void) close(fd);
2000 if (retval != bufsize) {
2001 return (-1);
2002 }
2003
2004 free_segment_hash(segment, sec_hash);
2005
2006 *newsection = sec_hash->obj_hdl;
2007 sec_hash->u.sec_obj->num_of_segment = sec_layout->segmentcount;
2008
2009 return (0);
2010 }
2011
2012 /*
2013 * Description :
2014 * sun_fru_read_segment() reads the raw contents of a segment.
2015 *
2016 * Arguments : segment_hdl_t : segment handle.
2017 * void * : buffer containing segment data when function returns.
2018 * size_t :number of bytes.
2019 *
2020 * Return :
2021 * int
2022 * On success, the number of bytes read is returned;
2023 *
2024 * Notes :
2025 * Segments containing packets can be read in structured fashion
2026 * using the fru_get_packets() and fru_get_payload() primitives;the
2027 * entire byte range of a segment can be read using
2028 * fru_read_segment().
2029 */
2030 /*ARGSUSED*/
2031 static ssize_t
sun_fru_read_segment(segment_hdl_t segment,void * buffer,size_t nbytes,door_cred_t * cred)2032 sun_fru_read_segment(segment_hdl_t segment, void *buffer, size_t nbytes,
2033 door_cred_t *cred)
2034 {
2035 int fd;
2036 int retval;
2037 hash_obj_t *seg_hash;
2038 hash_obj_t *sec_hash;
2039 hash_obj_t *cont_hash;
2040 format_t format;
2041
2042 /* segment hash object */
2043 seg_hash = lookup_handle_object(segment, SEGMENT_TYPE);
2044 if (seg_hash == NULL) {
2045 return (-1);
2046 }
2047
2048 /* section hash object */
2049 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
2050 SECTION_TYPE);
2051 if (sec_hash == NULL) {
2052 return (-1);
2053 }
2054
2055 /* container hash object */
2056 cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl,
2057 CONTAINER_TYPE);
2058 if (cont_hash == NULL) {
2059 return (-1);
2060 }
2061 format = cont_hash->u.cont_obj->format;
2062
2063 if (seg_hash->u.seg_obj->segment.length < nbytes) {
2064 return (-1);
2065 }
2066
2067 fd = open_file();
2068 if (fd < 0) {
2069 return (-1);
2070 }
2071
2072 retval = pread_new(fd, buffer, nbytes,
2073 seg_hash->u.seg_obj->segment.offset, &format);
2074 (void) close(fd);
2075 if (retval != nbytes) {
2076 return (-1);
2077 }
2078 return (nbytes);
2079 }
2080
2081 /*
2082 * Description :
2083 * sun_fru_write_segment() writes a raw segment.
2084 *
2085 * Arguments : segment_hdl_t :segment handle.
2086 * const void * : data buffer.
2087 * size_t : number of bytes.
2088 * segment_hdl_t : new segment handle.
2089 *
2090 * Returns :
2091 * int
2092 * On success, the number of bytes written is returned
2093 *
2094 */
2095 /*ARGSUSED*/
2096 static int
sun_fru_write_segment(segment_hdl_t segment,const void * data,size_t nbytes,segment_hdl_t * newsegment,door_cred_t * cred)2097 sun_fru_write_segment(segment_hdl_t segment, const void *data, size_t nbytes,
2098 segment_hdl_t *newsegment, door_cred_t *cred)
2099 {
2100 return (ENOTSUP);
2101 }
2102
2103
2104 static int
get_packet(int device_fd,void * buffer,int size,int offset,format_t * format)2105 get_packet(int device_fd, void *buffer, int size, int offset, format_t *format)
2106 {
2107 int retval;
2108
2109 retval = pread_new(device_fd, (char *)buffer, size, offset, format);
2110 if (retval != -1) {
2111 return (0);
2112 }
2113 return (-1);
2114 }
2115
2116 static uint32_t
get_checksum_crc(hash_obj_t * seg_hash,int data_size)2117 get_checksum_crc(hash_obj_t *seg_hash, int data_size)
2118 {
2119 int protection;
2120 int offset = 0;
2121 uint32_t crc;
2122 hash_obj_t *sec_hash;
2123 hash_obj_t *pkt_hash;
2124 unsigned char *buffer;
2125
2126 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
2127 SECTION_TYPE);
2128 if (sec_hash == NULL) {
2129 return ((uint32_t)-1);
2130 }
2131
2132 buffer = alloca(data_size);
2133 if (buffer == NULL) {
2134 return ((uint32_t)-1);
2135 }
2136
2137 /* traverse the packet object list for all the tags and payload */
2138 for (pkt_hash = seg_hash->u.seg_obj->pkt_obj_list; pkt_hash != NULL;
2139 pkt_hash = pkt_hash->u.pkt_obj->next) {
2140 (void) memcpy(buffer + offset, &pkt_hash->u.pkt_obj->tag,
2141 pkt_hash->u.pkt_obj->tag_size);
2142 offset += pkt_hash->u.pkt_obj->tag_size;
2143 (void) memcpy(buffer + offset, pkt_hash->u.pkt_obj->payload,
2144 pkt_hash->u.pkt_obj->paylen);
2145 offset += pkt_hash->u.pkt_obj->paylen;
2146 }
2147
2148 protection = sec_hash->u.sec_obj->section.protection;
2149
2150 if (protection == READ_ONLY_SECTION) { /* read-only section */
2151 crc = compute_crc32(buffer, data_size);
2152 } else { /* read/write section */
2153 crc = compute_checksum32(buffer, data_size);
2154 }
2155 return (crc); /* computed crc */
2156 }
2157
2158 static int
get_packets(hash_obj_t * seg_hash,int device_fd,int offset,int length)2159 get_packets(hash_obj_t *seg_hash, int device_fd, int offset, int length)
2160 {
2161 int tag_size;
2162 int paylen;
2163 int retval;
2164 int seg_limit = 0;
2165 int pktcnt = 0;
2166 char *data;
2167 uint32_t crc;
2168 uint32_t origcrc;
2169 fru_tag_t tag;
2170 hash_obj_t *pkt_hash_obj;
2171 fru_segdesc_t *segdesc;
2172 fru_tagtype_t tagtype;
2173 format_t format;
2174 hash_obj_t *cont_hash;
2175
2176 cont_hash = get_container_hash_object(PACKET_TYPE, seg_hash->obj_hdl);
2177 if (cont_hash == NULL) {
2178 return (NULL);
2179 }
2180 format = cont_hash->u.cont_obj->format;
2181
2182 retval = get_packet(device_fd, &tag, sizeof (fru_tag_t), offset,
2183 &format);
2184 if (retval == -1) {
2185 return (-1);
2186 }
2187
2188 seg_hash->u.seg_obj->trailer_offset = offset;
2189
2190 data = (char *)&tag;
2191 while (data[0] != SEG_TRAILER_TAG) {
2192 tagtype = get_tag_type(&tag); /* verify tag type */
2193 if (tagtype == -1) {
2194 return (-1);
2195 }
2196
2197 tag_size = get_tag_size(tagtype);
2198 if (tag_size == -1) {
2199 return (-1);
2200 }
2201
2202 seg_limit += tag_size;
2203 if (seg_limit > length) {
2204 return (-1);
2205 }
2206
2207 paylen = get_payload_length((void *)&tag);
2208 if (paylen == -1) {
2209 return (-1);
2210 }
2211
2212 seg_limit += paylen;
2213 if (seg_limit > length) {
2214 return (-1);
2215 }
2216
2217 pkt_hash_obj = create_packet_hash_object();
2218 if (pkt_hash_obj == NULL) {
2219 return (-1);
2220 }
2221
2222 pkt_hash_obj->u.pkt_obj->payload = malloc(paylen);
2223 if (pkt_hash_obj->u.pkt_obj->payload == NULL) {
2224 free(pkt_hash_obj);
2225 return (-1);
2226 }
2227
2228 offset += tag_size;
2229 retval = pread_new(device_fd, pkt_hash_obj->u.pkt_obj->payload,
2230 paylen, offset, &format);
2231 if (retval != paylen) {
2232 free(pkt_hash_obj->u.pkt_obj->payload);
2233 free(pkt_hash_obj);
2234 return (-1);
2235 }
2236
2237 /* don't change this */
2238 pkt_hash_obj->u.pkt_obj->tag.raw_data = 0;
2239 (void) memcpy(&pkt_hash_obj->u.pkt_obj->tag, &tag, tag_size);
2240 pkt_hash_obj->u.pkt_obj->paylen = paylen;
2241 pkt_hash_obj->u.pkt_obj->tag_size = tag_size;
2242 pkt_hash_obj->u.pkt_obj->payload_offset = offset;
2243
2244 offset += paylen;
2245
2246 add_hashobject_to_hashtable(pkt_hash_obj, PACKET_TYPE);
2247 add_to_pkt_object_list(seg_hash, pkt_hash_obj);
2248
2249 pktcnt++;
2250
2251 retval = get_packet(device_fd, &tag, sizeof (fru_tag_t),
2252 offset, &format);
2253 if (retval == -1) {
2254 return (retval);
2255 }
2256
2257 data = (char *)&tag;
2258 }
2259
2260 segdesc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor;
2261
2262 seg_hash->u.seg_obj->trailer_offset = offset;
2263
2264 if (!segdesc->field.ignore_checksum) {
2265 crc = get_checksum_crc(seg_hash, seg_limit);
2266 offset = seg_hash->u.seg_obj->segment.offset;
2267
2268 retval = pread_new(device_fd, &origcrc, sizeof (origcrc),
2269 offset + seg_limit + 1, &format);
2270 if (retval != sizeof (origcrc)) {
2271 return (-1);
2272 }
2273
2274 if (origcrc != crc) {
2275 seg_hash->u.seg_obj->trailer_offset = offset;
2276 return (-1);
2277 }
2278 }
2279 return (pktcnt);
2280 }
2281
2282 /*
2283 * Description :
2284 * sun_fru_get_num_packets() returns the current number of packets
2285 * in a segment.
2286 *
2287 * Arguments : segment_hdl_t : segment handle.
2288 *
2289 * Return :
2290 * int
2291 * On success, the number of packets is returned;
2292 * -1 on failure.
2293 */
2294 /*ARGSUSED*/
2295 static int
sun_fru_get_num_packets(segment_hdl_t segment,door_cred_t * cred)2296 sun_fru_get_num_packets(segment_hdl_t segment, door_cred_t *cred)
2297 {
2298 int device_fd;
2299 int pktcnt;
2300 int length;
2301 uint16_t offset;
2302 hash_obj_t *cont_hash_obj;
2303 hash_obj_t *seg_hash;
2304 fru_segdesc_t *segdesc;
2305 segment_obj_t *segment_object;
2306
2307 seg_hash = lookup_handle_object(segment, SEGMENT_TYPE);
2308 if (seg_hash == NULL) {
2309 return (-1);
2310 }
2311
2312 segment_object = seg_hash->u.seg_obj;
2313 if (segment_object == NULL) {
2314 return (-1);
2315 }
2316
2317
2318 segdesc = (fru_segdesc_t *)&segment_object->segment.descriptor;
2319 if (segdesc->field.opaque) {
2320 return (0);
2321 }
2322
2323 offset = segment_object->segment.offset;
2324 length = segment_object->segment.length;
2325
2326 cont_hash_obj = get_container_hash_object(SEGMENT_TYPE,
2327 segment_object->section_hdl);
2328
2329 if (cont_hash_obj == NULL) {
2330 return (-1);
2331 }
2332
2333 if (seg_hash->u.seg_obj->pkt_obj_list != NULL) {
2334 return (segment_object->num_of_packets);
2335 }
2336
2337 segment_object->num_of_packets = 0;
2338 device_fd = open_file();
2339 if (device_fd < 0) {
2340 return (-1);
2341 }
2342
2343 pktcnt = get_packets(seg_hash, device_fd, offset,
2344 length);
2345 if (pktcnt == -1) {
2346 free_pkt_object_list(seg_hash);
2347 seg_hash->u.seg_obj->pkt_obj_list = NULL;
2348 }
2349
2350 segment_object->num_of_packets = pktcnt;
2351 (void) close(device_fd);
2352
2353 return (segment_object->num_of_packets);
2354 }
2355
2356 /*
2357 * Description :
2358 * sun_fru_get_packets() fills an array of structures
2359 * representing the packets in a segment.
2360 *
2361 * Arguments : segment_hdl_t : segment handle.
2362 * packet_t : packet buffer.
2363 * int : maximum number of packets.
2364 *
2365 * Return :
2366 * int
2367 * On success, the number of packet structures written is returned;
2368 * On failure -1 is returned;
2369 *
2370 */
2371 /*ARGSUSED*/
2372 static int
sun_fru_get_packets(segment_hdl_t segment,packet_t * packet,int maxpackets,door_cred_t * cred)2373 sun_fru_get_packets(segment_hdl_t segment, packet_t *packet, int maxpackets,
2374 door_cred_t *cred)
2375 {
2376 int count;
2377 hash_obj_t *seg_hash_obj;
2378 hash_obj_t *pkt_hash_obj;
2379
2380 /* segment hash object */
2381 seg_hash_obj = lookup_handle_object(segment, SEGMENT_TYPE);
2382 if (seg_hash_obj == NULL) {
2383 return (-1);
2384 }
2385
2386 if (seg_hash_obj->u.seg_obj->num_of_packets != maxpackets) {
2387 return (-1);
2388 }
2389
2390 pkt_hash_obj = seg_hash_obj->u.seg_obj->pkt_obj_list;
2391 if (pkt_hash_obj == NULL) {
2392 return (-1);
2393 }
2394
2395 for (count = 0; count < maxpackets; count++, packet++) {
2396 packet->handle = pkt_hash_obj->obj_hdl;
2397 packet->tag = 0;
2398 (void) memcpy(&packet->tag, &pkt_hash_obj->u.pkt_obj->tag,
2399 pkt_hash_obj->u.pkt_obj->tag_size);
2400 pkt_hash_obj = pkt_hash_obj->u.pkt_obj->next;
2401 }
2402
2403 return (0);
2404 }
2405
2406 /*
2407 * Description :
2408 * sun_fru_get_payload() copies the contents of a packet's payload.
2409 *
2410 * Arguments : packet_hdl_t : packet handle.
2411 * void * : payload buffer.
2412 * size_t : sizeof the buffer.
2413 *
2414 * Return :
2415 * int
2416 * On success, the number of bytes copied is returned; On error
2417 * -1 returned.
2418 */
2419 /*ARGSUSED*/
2420 static ssize_t
sun_fru_get_payload(packet_hdl_t packet,void * buffer,size_t nbytes,door_cred_t * cred)2421 sun_fru_get_payload(packet_hdl_t packet, void *buffer, size_t nbytes,
2422 door_cred_t *cred)
2423 {
2424 hash_obj_t *packet_hash_obj;
2425
2426 /* packet hash object */
2427 packet_hash_obj = lookup_handle_object(packet, PACKET_TYPE);
2428 if (packet_hash_obj == NULL) {
2429 return (-1);
2430 }
2431
2432 /* verify payload length */
2433 if (nbytes != packet_hash_obj->u.pkt_obj->paylen) {
2434 return (-1);
2435 }
2436
2437 (void) memcpy(buffer, packet_hash_obj->u.pkt_obj->payload, nbytes);
2438 return (nbytes);
2439 }
2440
2441 /*
2442 * Description :
2443 * sun_fru_update_payload() writes the contents of a packet's
2444 * payload.
2445 *
2446 * Arguments : packet_hdl_t : packet handle.
2447 * const void * : data buffer.
2448 * size_t : buffer size.
2449 * packet_hdl_t : new packet handle.
2450 *
2451 * Return :
2452 * int
2453 * On success, 0 is returned; on failure
2454 * -1 is returned.
2455 */
2456 /*ARGSUSED*/
2457 static int
sun_fru_update_payload(packet_hdl_t packet,const void * data,size_t nbytes,packet_hdl_t * newpacket,door_cred_t * cred)2458 sun_fru_update_payload(packet_hdl_t packet, const void *data, size_t nbytes,
2459 packet_hdl_t *newpacket, door_cred_t *cred)
2460 {
2461 int fd;
2462 int segment_offset;
2463 int trailer_offset;
2464 int retval;
2465 uint32_t crc;
2466 hash_obj_t *pkt_hash;
2467 hash_obj_t *seg_hash;
2468 hash_obj_t *sec_hash;
2469 hash_obj_t *cont_hash;
2470 fru_segdesc_t *desc;
2471 format_t format;
2472
2473 /* check the effective uid of the client */
2474 if (cred->dc_euid != 0) {
2475 errno = EPERM;
2476 return (-1); /* not a root */
2477 }
2478
2479 /* packet hash object */
2480 pkt_hash = lookup_handle_object(packet, PACKET_TYPE);
2481 if (pkt_hash == NULL) {
2482 return (-1);
2483 }
2484
2485 /* segment hash object */
2486 seg_hash = lookup_handle_object(pkt_hash->u.pkt_obj->segment_hdl,
2487 SEGMENT_TYPE);
2488 if (seg_hash == NULL) {
2489 return (-1);
2490 }
2491
2492 /* check for write perm. */
2493 desc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor;
2494 if (!(desc->field.field_perm & SEGMENT_WRITE)) {
2495 errno = EPERM;
2496 return (-1); /* write not allowed */
2497 }
2498
2499 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
2500 SECTION_TYPE);
2501 if (sec_hash == NULL) {
2502 return (-1);
2503 }
2504
2505 if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) {
2506 errno = EPERM;
2507 return (-1); /* read-only section */
2508 }
2509
2510 cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl,
2511 CONTAINER_TYPE);
2512 if (cont_hash == NULL) {
2513 return (-1);
2514 }
2515
2516 format = cont_hash->u.cont_obj->format;
2517
2518 if (pkt_hash->u.pkt_obj->paylen != nbytes) {
2519 return (-1);
2520 }
2521
2522 (void) memcpy(pkt_hash->u.pkt_obj->payload, (char *)data, nbytes);
2523 fd = open_file();
2524 if (fd < 0) {
2525 return (-1);
2526 }
2527
2528 trailer_offset = seg_hash->u.seg_obj->trailer_offset;
2529 segment_offset = seg_hash->u.seg_obj->segment.offset;
2530
2531 crc = get_checksum_crc(seg_hash, (trailer_offset - segment_offset));
2532 retval = pwrite_new(fd, data, nbytes,
2533 pkt_hash->u.pkt_obj->payload_offset, &format);
2534 if (retval != nbytes) {
2535 (void) close(fd);
2536 return (-1);
2537 }
2538
2539 retval = pwrite_new(fd, &crc, sizeof (crc),
2540 trailer_offset + 1, &format);
2541 (void) close(fd);
2542 if (retval != sizeof (crc)) {
2543 return (-1);
2544 }
2545 *newpacket = packet;
2546 return (0);
2547 }
2548
2549 /*
2550 * Description :
2551 * sun_fru_append_packet() appends a packet to a segment.
2552 *
2553 * Arguments :
2554 * segment_hdl_t segment
2555 * A handle for the segment to which the packet will be appended.
2556 *
2557 * packet_t *packet
2558 * On entry, the "tag" component of "packet" specifies the tag
2559 * value for the added packet; the "handle" component is ignored.
2560 * On return, the "handle" component is set to the handle of the
2561 * appended packet.
2562 *
2563 * const void *payload
2564 * A pointer to the caller's buffer containing the payload data for
2565 * the appended packet.
2566 *
2567 * size_t nbytes
2568 * The size of the caller buffer.
2569 *
2570 * Return :
2571 * int
2572 * On success, 0 is returned; on error -1 is returned;
2573 */
2574 static int
sun_fru_append_packet(segment_hdl_t segment,packet_t * packet,const void * payload,size_t nbytes,segment_hdl_t * newsegment,door_cred_t * cred)2575 sun_fru_append_packet(segment_hdl_t segment, packet_t *packet,
2576 const void *payload, size_t nbytes, segment_hdl_t *newsegment,
2577 door_cred_t *cred)
2578 {
2579 int trailer_offset;
2580 int tag_size;
2581 int fd;
2582 int retval;
2583 char trailer[] = {0x0c, 0x00, 0x00, 0x00, 0x00};
2584 uint32_t crc;
2585 hash_obj_t *seg_hash;
2586 hash_obj_t *sec_hash;
2587 hash_obj_t *pkt_hash;
2588 hash_obj_t *cont_hash;
2589 fru_tagtype_t tagtype;
2590 fru_segdesc_t *desc;
2591 format_t format;
2592
2593 /* check the effective uid of the client */
2594 if (cred->dc_euid != 0) {
2595 errno = EPERM;
2596 return (-1); /* not a root */
2597 }
2598
2599 seg_hash = lookup_handle_object(segment, SEGMENT_TYPE);
2600 if (seg_hash == NULL) {
2601 return (-1);
2602 }
2603
2604 /* check for write perm. */
2605 desc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor;
2606 if (!(desc->field.field_perm & SEGMENT_WRITE)) {
2607 errno = EPERM;
2608 return (-1); /* write not allowed */
2609 }
2610
2611 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
2612 SECTION_TYPE);
2613 if (sec_hash == NULL) {
2614 return (-1);
2615 }
2616
2617 if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) {
2618 errno = EPERM;
2619 return (-1); /* read-only section */
2620 }
2621
2622 trailer_offset = seg_hash->u.seg_obj->trailer_offset;
2623
2624 /*
2625 * if trailer offset is 0 than parse the segment data to get the trailer
2626 * offset to compute the remaining space left in the segment area for
2627 * new packet to be added.
2628 */
2629 if (trailer_offset == 0) {
2630 (void) sun_fru_get_num_packets(segment, cred);
2631 trailer_offset = seg_hash->u.seg_obj->trailer_offset;
2632 }
2633
2634 tagtype = get_tag_type((void *)&packet->tag);
2635 if (tagtype == -1) {
2636 return (-1);
2637 }
2638
2639 tag_size = get_tag_size(tagtype);
2640 if (tag_size == -1) {
2641 return (-1);
2642 }
2643
2644 if (seg_hash->u.seg_obj->segment.length >
2645 ((trailer_offset - seg_hash->u.seg_obj->segment.offset) +
2646 tag_size + nbytes +
2647 sizeof (char) + sizeof (uint32_t))) {
2648 /* create new packet hash */
2649 pkt_hash = create_packet_hash_object();
2650 if (pkt_hash == NULL) {
2651 return (-1);
2652 }
2653
2654 /* tag initialization */
2655 (void) memcpy(&pkt_hash->u.pkt_obj->tag, &packet->tag,
2656 tag_size);
2657 pkt_hash->u.pkt_obj->tag_size = tag_size;
2658
2659 /* payload inititalization */
2660 pkt_hash->u.pkt_obj->payload = malloc(nbytes);
2661 if (pkt_hash->u.pkt_obj->payload == NULL) {
2662 free(pkt_hash);
2663 return (-1);
2664 }
2665
2666 (void) memcpy(pkt_hash->u.pkt_obj->payload, payload, nbytes);
2667 pkt_hash->u.pkt_obj->paylen = nbytes;
2668 pkt_hash->u.pkt_obj->payload_offset = trailer_offset + tag_size;
2669
2670 /* add to hash table */
2671 add_hashobject_to_hashtable(pkt_hash, PACKET_TYPE);
2672
2673 add_to_pkt_object_list(seg_hash, pkt_hash);
2674
2675 cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl,
2676 CONTAINER_TYPE);
2677 if (cont_hash == NULL) {
2678 return (-1);
2679 }
2680 format = cont_hash->u.cont_obj->format;
2681
2682 fd = open_file();
2683 if (fd < 0) {
2684 return (-1);
2685 }
2686
2687 /* update the trailer offset */
2688 trailer_offset += tag_size + nbytes;
2689
2690 /* calculate new checksum */
2691 crc = get_checksum_crc(seg_hash, (trailer_offset -
2692 seg_hash->u.seg_obj->segment.offset));
2693
2694 retval = pwrite_new(fd, &packet->tag, tag_size, trailer_offset
2695 - (tag_size + nbytes), &format);
2696 if (retval != tag_size) {
2697 (void) close(fd);
2698 return (-1);
2699 }
2700
2701 retval = pwrite_new(fd, payload, nbytes,
2702 trailer_offset - nbytes, &format);
2703 if (retval != nbytes) {
2704 (void) close(fd);
2705 return (-1);
2706 }
2707
2708 retval = pwrite_new(fd, trailer, sizeof (trailer),
2709 trailer_offset, &format);
2710 if (retval != sizeof (trailer)) {
2711 (void) close(fd);
2712 return (-1);
2713 }
2714
2715 retval = pwrite_new(fd, &crc, sizeof (crc),
2716 trailer_offset + 1, &format);
2717 (void) close(fd);
2718 if (retval != sizeof (crc)) {
2719 return (-1);
2720 }
2721
2722 seg_hash->u.seg_obj->trailer_offset = trailer_offset;
2723 seg_hash->u.seg_obj->num_of_packets += 1;
2724
2725 *newsegment = segment; /* return new segment handle */
2726 return (0);
2727 } else {
2728 errno = EAGAIN;
2729 }
2730
2731 return (-1);
2732 }
2733
2734 static void
adjust_packets(int fd,hash_obj_t * free_obj,hash_obj_t * object_list)2735 adjust_packets(int fd, hash_obj_t *free_obj, hash_obj_t *object_list)
2736 {
2737 int retval;
2738 uint32_t new_offset;
2739 hash_obj_t *hash_ptr;
2740 format_t format;
2741 hash_obj_t *hash_obj;
2742
2743 hash_obj = lookup_handle_object(free_obj->obj_hdl, PACKET_TYPE);
2744 if (hash_obj == NULL) {
2745 return;
2746 }
2747 hash_obj = get_container_hash_object(PACKET_TYPE,
2748 hash_obj->u.pkt_obj->segment_hdl);
2749 if (hash_obj == NULL) {
2750 return;
2751 }
2752 format = hash_obj->u.cont_obj->format;
2753
2754 new_offset = free_obj->u.pkt_obj->payload_offset
2755 - free_obj->u.pkt_obj->tag_size;
2756 for (hash_ptr = object_list; hash_ptr != NULL;
2757 hash_ptr = hash_ptr->u.pkt_obj->next) {
2758 retval = pwrite_new(fd, &hash_ptr->u.pkt_obj->tag,
2759 hash_ptr->u.pkt_obj->tag_size, new_offset, &format);
2760 if (retval != hash_ptr->u.pkt_obj->tag_size) {
2761 return;
2762 }
2763 new_offset += hash_ptr->u.pkt_obj->tag_size;
2764 hash_ptr->u.pkt_obj->payload_offset = new_offset;
2765 retval = pwrite_new(fd, hash_ptr->u.pkt_obj->payload,
2766 hash_ptr->u.pkt_obj->paylen, new_offset, &format);
2767 if (retval != hash_ptr->u.pkt_obj->paylen) {
2768 return;
2769 }
2770 new_offset += hash_ptr->u.pkt_obj->paylen;
2771 }
2772 }
2773
2774 static void
free_packet_object(handle_t handle,hash_obj_t * seg_hash)2775 free_packet_object(handle_t handle, hash_obj_t *seg_hash)
2776 {
2777 hash_obj_t *pkt_hash;
2778 hash_obj_t *next_hash;
2779
2780 pkt_hash = seg_hash->u.seg_obj->pkt_obj_list;
2781 if (pkt_hash == NULL) {
2782 return;
2783 }
2784
2785 if (pkt_hash->obj_hdl == handle) {
2786 seg_hash->u.seg_obj->pkt_obj_list = pkt_hash->u.pkt_obj->next;
2787 } else {
2788 while (pkt_hash->obj_hdl != handle) {
2789 next_hash = pkt_hash;
2790 pkt_hash = pkt_hash->u.pkt_obj->next;
2791 if (pkt_hash == NULL) {
2792 return;
2793 }
2794 }
2795 next_hash->u.pkt_obj->next = pkt_hash->u.pkt_obj->next;
2796 }
2797
2798 if (pkt_hash->prev == NULL) {
2799 hash_table[(pkt_hash->obj_hdl % TABLE_SIZE)] = pkt_hash->next;
2800 if (pkt_hash->next != NULL) {
2801 pkt_hash->next->prev = NULL;
2802 }
2803 } else {
2804 pkt_hash->prev->next = pkt_hash->next;
2805 if (pkt_hash->next != NULL) {
2806 pkt_hash->next->prev = pkt_hash->prev;
2807 }
2808 }
2809
2810 free(pkt_hash->u.pkt_obj->payload);
2811 free(pkt_hash->u.pkt_obj);
2812 free(pkt_hash);
2813 }
2814
2815 /*
2816 * Description :
2817 * sun_fru_delete_packet() deletes a packet from a segment.
2818 *
2819 * Arguments : packet_hdl_t : packet number to be deleted.
2820 * segment_hdl_t : new segment handler.
2821 *
2822 * Return :
2823 * int
2824 * On success, 0 is returned; on error, -1.
2825 *
2826 * NOTES
2827 * Packets are adjacent; thus, deleting a packet requires moving
2828 * succeeding packets to compact the resulting hole.
2829 */
2830 static int
sun_fru_delete_packet(packet_hdl_t packet,segment_hdl_t * newsegment,door_cred_t * cred)2831 sun_fru_delete_packet(packet_hdl_t packet, segment_hdl_t *newsegment,
2832 door_cred_t *cred)
2833 {
2834 int retval;
2835 int fd;
2836 char trailer[] = { 0x0c, 0x00, 0x00, 0x00, 0x00};
2837 uint32_t crc;
2838 hash_obj_t *tmp_obj;
2839 hash_obj_t *pkt_hash;
2840 hash_obj_t *sec_hash;
2841 hash_obj_t *cont_hash;
2842 hash_obj_t *prev_obj;
2843 hash_obj_t *seg_hash;
2844 fru_segdesc_t *desc;
2845 format_t format;
2846
2847 /* check the effective uid of the client */
2848 if (cred->dc_euid != 0) {
2849 errno = EPERM;
2850 return (-1); /* not a root */
2851 }
2852
2853 /* packet hash object */
2854 pkt_hash = lookup_handle_object(packet, PACKET_TYPE);
2855 if (pkt_hash == NULL) {
2856 return (-1);
2857 }
2858
2859 /* segment hash object */
2860 seg_hash = lookup_handle_object(pkt_hash->u.pkt_obj->segment_hdl,
2861 SEGMENT_TYPE);
2862 if (seg_hash == NULL) {
2863 return (-1);
2864 }
2865
2866 /* check for write perm. */
2867 desc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor;
2868 if (!(desc->field.field_perm & SEGMENT_WRITE)) {
2869 errno = EPERM;
2870 return (-1); /* write not allowed */
2871 }
2872
2873 /* section hash object */
2874 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
2875 SECTION_TYPE);
2876 if (sec_hash == NULL) {
2877 return (-1);
2878 }
2879
2880 if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) {
2881 errno = EPERM;
2882 return (-1); /* read-only section */
2883 }
2884
2885 prev_obj = seg_hash->u.seg_obj->pkt_obj_list;
2886 if (prev_obj == NULL) {
2887 return (-1);
2888 }
2889
2890 /* container hash object */
2891 cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl,
2892 CONTAINER_TYPE);
2893 if (cont_hash == NULL) {
2894 return (-1);
2895 }
2896
2897 format = cont_hash->u.cont_obj->format;
2898
2899 fd = open_file();
2900 if (fd < 0) {
2901 return (-1);
2902 }
2903
2904 if (prev_obj->obj_hdl == packet) { /* first object to be deleted */
2905 adjust_packets(fd, prev_obj, prev_obj->u.pkt_obj->next);
2906 seg_hash->u.seg_obj->trailer_offset -=
2907 (prev_obj->u.pkt_obj->tag_size
2908 + prev_obj->u.pkt_obj->paylen);
2909 free_packet_object(packet, seg_hash);
2910 } else {
2911 for (tmp_obj = prev_obj;
2912 tmp_obj != NULL; tmp_obj = tmp_obj->u.pkt_obj->next) {
2913 /* found the object */
2914 if (tmp_obj->obj_hdl == packet) {
2915 adjust_packets(fd, tmp_obj,
2916 tmp_obj->u.pkt_obj->next);
2917 seg_hash->u.seg_obj->trailer_offset -=
2918 (tmp_obj->u.pkt_obj->tag_size
2919 + tmp_obj->u.pkt_obj->paylen);
2920 free_packet_object(packet, seg_hash);
2921 }
2922 }
2923 }
2924
2925 seg_hash->u.seg_obj->num_of_packets -= 1;
2926
2927 /* calculate checksum */
2928 crc = get_checksum_crc(seg_hash, (seg_hash->u.seg_obj->trailer_offset
2929 - seg_hash->u.seg_obj->segment.offset));
2930 /* write trailer at new offset */
2931 retval = pwrite_new(fd, &trailer, sizeof (trailer),
2932 seg_hash->u.seg_obj->trailer_offset, &format);
2933 if (retval != sizeof (trailer)) {
2934 (void) close(fd);
2935 return (-1);
2936 }
2937
2938 /* write the checksum value */
2939 retval = pwrite_new(fd, &crc, sizeof (crc),
2940 seg_hash->u.seg_obj->trailer_offset + 1, &format);
2941 (void) close(fd);
2942 if (retval != sizeof (crc)) {
2943 return (-1);
2944 }
2945
2946 *newsegment = seg_hash->obj_hdl; /* return new segment handle */
2947 return (0);
2948 }
2949
2950 /*
2951 * Description :
2952 * sun_fru_close_container() removes the association between a
2953 * container and its handle. this routines free's up all the
2954 * hash object contained under container.
2955 *
2956 * Arguments :
2957 * container_hdl_t holds the file descriptor of the fru.
2958 *
2959 * Return :
2960 * int
2961 * return 0.
2962 *
2963 */
2964 /* ARGSUSED */
2965 static int
sun_fru_close_container(container_hdl_t container)2966 sun_fru_close_container(container_hdl_t container)
2967 {
2968 hash_obj_t *hash_obj;
2969 hash_obj_t *prev_hash;
2970 hash_obj_t *sec_hash_obj;
2971 handle_t obj_hdl;
2972
2973 /* lookup for container hash object */
2974 hash_obj = lookup_handle_object(container, CONTAINER_TYPE);
2975 if (hash_obj == NULL) {
2976 return (0);
2977 }
2978
2979 /* points to section object list */
2980 sec_hash_obj = hash_obj->u.cont_obj->sec_obj_list;
2981
2982 /* traverse section object list */
2983 while (sec_hash_obj != NULL) {
2984
2985 /* traverse segment hash object in the section */
2986 while (sec_hash_obj->u.sec_obj->seg_obj_list != NULL) {
2987 /* object handle of the segment hash object */
2988 obj_hdl =
2989 sec_hash_obj->u.sec_obj->seg_obj_list->obj_hdl;
2990 free_segment_hash(obj_hdl, sec_hash_obj);
2991 }
2992
2993 /* going to free section hash object, relink the hash object */
2994 if (sec_hash_obj->prev == NULL) {
2995 hash_table[(sec_hash_obj->obj_hdl % TABLE_SIZE)]
2996 = sec_hash_obj->next;
2997 if (sec_hash_obj->next != NULL) {
2998 sec_hash_obj->next->prev = NULL;
2999 }
3000 } else {
3001 sec_hash_obj->prev->next = sec_hash_obj->next;
3002 if (sec_hash_obj->next != NULL) {
3003 sec_hash_obj->next->prev = sec_hash_obj->prev;
3004 }
3005 }
3006
3007 free(sec_hash_obj->u.sec_obj); /* free section hash object */
3008
3009 prev_hash = sec_hash_obj;
3010
3011 sec_hash_obj = sec_hash_obj->u.sec_obj->next;
3012
3013 free(prev_hash); /* free section hash */
3014 }
3015
3016 /* free container hash object */
3017 if (hash_obj->prev == NULL) {
3018 hash_table[(sec_hash_obj->obj_hdl % TABLE_SIZE)] =
3019 hash_obj->next;
3020 if (hash_obj->next != NULL) {
3021 hash_obj->next->prev = NULL;
3022 }
3023 } else {
3024 hash_obj->prev->next = hash_obj->next;
3025 if (hash_obj->next != NULL) {
3026 hash_obj->next->prev = hash_obj->prev;
3027 }
3028 }
3029
3030 free(hash_obj->u.cont_obj);
3031 free(hash_obj);
3032 return (0);
3033 }
3034
3035 /*
3036 * FRU ACCESS API
3037 */
3038
3039 /*
3040 * Description :
3041 * fru_is_data_available checks if the fruid information
3042 * is available or not on a give fru
3043 *
3044 * Arguments :
3045 * picl_nodehdl_t hold picl node handle of the fru.
3046 *
3047 * Return :
3048 * int
3049 * return 0 - if fruid is not present.
3050 * return 1 - if fruid is present.
3051 */
3052 int
fru_is_data_available(picl_nodehdl_t fruh)3053 fru_is_data_available(picl_nodehdl_t fruh)
3054 {
3055 int retval, ret;
3056 uint8_t slot_no;
3057 picl_nodehdl_t parenth;
3058 format_t fru_format;
3059 hash_obj_t *cont_hash_obj;
3060
3061 if (is_valid_chassis == -1) {
3062 if (fruaccess_platmod_check_chassis() == 0) {
3063 is_valid_chassis = 1;
3064 } else {
3065 is_valid_chassis = 0;
3066 }
3067 }
3068
3069 if (!is_valid_chassis) {
3070 return (0);
3071 }
3072
3073 retval = ptree_get_propval_by_name(fruh, PICL_PROP_PARENT,
3074 &parenth, sizeof (picl_nodehdl_t));
3075 if (retval != PICL_SUCCESS) {
3076 return (0);
3077 }
3078
3079 if (fruaccess_platmod_check_fru(parenth) != 0) {
3080 return (0);
3081 }
3082
3083 retval = ptree_get_propval_by_name(parenth, PICL_PROP_GEO_ADDR,
3084 &slot_no, sizeof (uint8_t));
3085 if (retval != PICL_SUCCESS) {
3086 return (0);
3087 }
3088
3089 if (fruaccess_platmod_init_format(slot_no, &fru_format) !=
3090 PICL_SUCCESS) {
3091 return (0);
3092 }
3093
3094 ret = is_fru_data_available(precedence, slot_no, &fru_format);
3095 if (ret && (fru_format.format != NO_FRUDATA)) {
3096 goto create;
3097 } else {
3098 return (0);
3099 }
3100 create:
3101
3102 cont_hash_obj = create_container_hash_object();
3103 if (cont_hash_obj == NULL) {
3104 return (0);
3105 }
3106
3107 cont_hash_obj->obj_hdl = fruh;
3108 cont_hash_obj->u.cont_obj->format = fru_format;
3109
3110 /* if both formats are present follow the precedence */
3111 if (fru_format.format == 0x3) {
3112 if (precedence == IPMI_FORMAT) {
3113 cont_hash_obj->u.cont_obj->format.format = IPMI_FORMAT;
3114 } else {
3115 cont_hash_obj->u.cont_obj->format.format = SUN_FORMAT;
3116 }
3117 }
3118 add_hashobject_to_hashtable(cont_hash_obj, CONTAINER_TYPE);
3119 return (1);
3120 }
3121
3122 /*
3123 * FRU ACCESS API
3124 */
3125
3126 /*
3127 * All the routines check the fruid format and redirects the call to
3128 * to appropriate routines depending on fruid format.
3129 * All SUN format routines start with sun_ prefix.
3130 * All IPMI format routines start with ipmi_ prefix.
3131 */
3132 container_hdl_t
fru_open_container(picl_nodehdl_t fru)3133 fru_open_container(picl_nodehdl_t fru)
3134 {
3135 hash_obj_t *hash_obj;
3136 format_t fru_format;
3137
3138 hash_obj = lookup_handle_object((handle_t)fru, CONTAINER_TYPE);
3139 if (hash_obj == NULL) {
3140 return (-1);
3141 }
3142 fru_format = hash_obj->u.cont_obj->format;
3143 return (fruaccess_func[fru_format.format - 1].open_container(fru));
3144 }
3145
3146 int
fru_close_container(container_hdl_t container)3147 fru_close_container(container_hdl_t container)
3148 {
3149 int ret;
3150 format_t fru_format;
3151 hash_obj_t *hash_obj;
3152
3153 hash_obj = lookup_handle_object(container, CONTAINER_TYPE);
3154 if (hash_obj == NULL) {
3155 return (-1);
3156 }
3157
3158 fru_format = hash_obj->u.cont_obj->format;
3159 ret = fruaccess_func[fru_format.format - 1].close_container(container);
3160 return (ret);
3161 }
3162
3163 int
fru_get_num_sections(container_hdl_t container,door_cred_t * cred)3164 fru_get_num_sections(container_hdl_t container, door_cred_t *cred)
3165 {
3166 int ret;
3167 format_t fru_format;
3168 hash_obj_t *hash_obj;
3169
3170 hash_obj = lookup_handle_object(container, CONTAINER_TYPE);
3171 if (hash_obj == NULL) {
3172 return (-1);
3173 }
3174 fru_format = hash_obj->u.cont_obj->format;
3175 ret = fruaccess_func[fru_format.format - 1].get_num_sections(container,
3176 cred);
3177 return (ret);
3178 }
3179
3180 int
fru_get_sections(container_hdl_t container,section_t * section,int max_sections,door_cred_t * cred)3181 fru_get_sections(container_hdl_t container, section_t *section,
3182 int max_sections, door_cred_t *cred)
3183 {
3184 int ret;
3185 format_t fru_format;
3186 hash_obj_t *hash_obj;
3187
3188 hash_obj = lookup_handle_object(container, CONTAINER_TYPE);
3189 if (hash_obj == NULL) {
3190 return (-1);
3191 }
3192 fru_format = hash_obj->u.cont_obj->format;
3193
3194 ret = fruaccess_func[fru_format.format - 1].get_sections(container,
3195 section, max_sections, cred);
3196 return (ret);
3197 }
3198
3199 int
fru_get_num_segments(section_hdl_t section,door_cred_t * rarg)3200 fru_get_num_segments(section_hdl_t section, door_cred_t *rarg)
3201 {
3202 int ret;
3203 format_t fru_format;
3204 hash_obj_t *hash_obj;
3205
3206 hash_obj = get_container_hash_object(SEGMENT_TYPE, section);
3207 if (hash_obj == NULL) {
3208 return (-1);
3209 }
3210 fru_format = hash_obj->u.cont_obj->format;
3211
3212 ret = fruaccess_func[fru_format.format - 1].get_num_segments(section,
3213 rarg);
3214 return (ret);
3215 }
3216
3217 int
fru_get_segments(section_hdl_t section,segment_t * segment,int max_segments,door_cred_t * rarg)3218 fru_get_segments(section_hdl_t section, segment_t *segment,
3219 int max_segments, door_cred_t *rarg)
3220 {
3221 int ret;
3222 format_t fru_format;
3223 hash_obj_t *hash_obj;
3224
3225 hash_obj = get_container_hash_object(SEGMENT_TYPE, section);
3226 if (hash_obj == NULL) {
3227 return (-1);
3228 }
3229 fru_format = hash_obj->u.cont_obj->format;
3230 ret = fruaccess_func[fru_format.format - 1].get_segments(section,
3231 segment, max_segments, rarg);
3232 return (ret);
3233 }
3234
3235 int
fru_add_segment(section_hdl_t section,segment_t * segment,section_hdl_t * newsection,door_cred_t * cred)3236 fru_add_segment(section_hdl_t section, segment_t *segment,
3237 section_hdl_t *newsection, door_cred_t *cred)
3238 {
3239 int ret;
3240 format_t fru_format;
3241 hash_obj_t *hash_obj;
3242
3243 hash_obj = get_container_hash_object(SEGMENT_TYPE, section);
3244 if (hash_obj == NULL) {
3245 return (-1);
3246 }
3247 fru_format = hash_obj->u.cont_obj->format;
3248
3249 ret = fruaccess_func[fru_format.format - 1].add_segment(section,
3250 segment, newsection, cred);
3251 return (ret);
3252 }
3253
3254 int
fru_delete_segment(segment_hdl_t segment,section_hdl_t * newsection,door_cred_t * cred)3255 fru_delete_segment(segment_hdl_t segment, section_hdl_t *newsection,
3256 door_cred_t *cred)
3257 {
3258 int ret;
3259 format_t fru_format;
3260 hash_obj_t *hash_obj;
3261
3262 hash_obj = get_container_hash_object(PACKET_TYPE, segment);
3263 if (hash_obj == NULL) {
3264 return (-1);
3265 }
3266 fru_format = hash_obj->u.cont_obj->format;
3267 ret = fruaccess_func[fru_format.format - 1].delete_segment(segment,
3268 newsection, cred);
3269 return (ret);
3270 }
3271
3272 ssize_t
fru_read_segment(segment_hdl_t segment,void * buffer,size_t nbytes,door_cred_t * cred)3273 fru_read_segment(segment_hdl_t segment, void *buffer, size_t nbytes,
3274 door_cred_t *cred)
3275 {
3276 ssize_t ret;
3277 format_t fru_format;
3278 hash_obj_t *hash_obj;
3279
3280 hash_obj = get_container_hash_object(PACKET_TYPE, segment);
3281 if (hash_obj == NULL) {
3282 return (-1);
3283 }
3284 fru_format = hash_obj->u.cont_obj->format;
3285 ret = fruaccess_func[fru_format.format - 1].read_segment(segment,
3286 buffer, nbytes, cred);
3287 return (ret);
3288 }
3289
3290 int
fru_write_segment(segment_hdl_t segment,const void * data,size_t nbytes,segment_hdl_t * newsegment,door_cred_t * cred)3291 fru_write_segment(segment_hdl_t segment, const void *data, size_t nbytes,
3292 segment_hdl_t *newsegment, door_cred_t *cred)
3293 {
3294 int ret;
3295 format_t fru_format;
3296 hash_obj_t *hash_obj;
3297
3298 hash_obj = get_container_hash_object(PACKET_TYPE, segment);
3299 if (hash_obj == NULL) {
3300 return (-1);
3301 }
3302 fru_format = hash_obj->u.cont_obj->format;
3303
3304 ret = fruaccess_func[fru_format.format - 1].write_segment(segment,
3305 data, nbytes, newsegment, cred);
3306 return (ret);
3307 }
3308
3309 int
fru_get_num_packets(segment_hdl_t segment,door_cred_t * cred)3310 fru_get_num_packets(segment_hdl_t segment, door_cred_t *cred)
3311 {
3312 int ret;
3313 format_t fru_format;
3314 hash_obj_t *hash_obj;
3315
3316 hash_obj = get_container_hash_object(PACKET_TYPE, segment);
3317 if (hash_obj == NULL) {
3318 return (-1);
3319 }
3320 fru_format = hash_obj->u.cont_obj->format;
3321
3322 ret = fruaccess_func[fru_format.format - 1].get_num_packets(segment,
3323 cred);
3324 return (ret);
3325 }
3326
3327 int
fru_get_packets(segment_hdl_t segment,packet_t * packet,int max_packets,door_cred_t * cred)3328 fru_get_packets(segment_hdl_t segment, packet_t *packet,
3329 int max_packets, door_cred_t *cred)
3330 {
3331 int ret;
3332 format_t fru_format;
3333 hash_obj_t *hash_obj;
3334
3335 hash_obj = get_container_hash_object(PACKET_TYPE, segment);
3336 if (hash_obj == NULL) {
3337 return (-1);
3338 }
3339 fru_format = hash_obj->u.cont_obj->format;
3340
3341 ret = fruaccess_func[fru_format.format - 1].get_packets(segment,
3342 packet, max_packets, cred);
3343 return (ret);
3344 }
3345
3346 ssize_t
fru_get_payload(packet_hdl_t packet,void * buffer,size_t nbytes,door_cred_t * cred)3347 fru_get_payload(packet_hdl_t packet, void *buffer,
3348 size_t nbytes, door_cred_t *cred)
3349 {
3350 ssize_t ret;
3351 format_t fru_format;
3352 hash_obj_t *hash_obj;
3353
3354 hash_obj = lookup_handle_object(packet, PACKET_TYPE);
3355 if (hash_obj == NULL) {
3356 return (-1);
3357 }
3358
3359 hash_obj = get_container_hash_object(PACKET_TYPE,
3360 hash_obj->u.pkt_obj->segment_hdl);
3361 if (hash_obj == NULL) {
3362 return (-1);
3363 }
3364 fru_format = hash_obj->u.cont_obj->format;
3365
3366 ret = fruaccess_func[fru_format.format - 1].get_payload(packet, buffer,
3367 nbytes, cred);
3368 return (ret);
3369 }
3370
3371 int
fru_update_payload(packet_hdl_t packet,const void * data,size_t nbytes,packet_hdl_t * newpacket,door_cred_t * cred)3372 fru_update_payload(packet_hdl_t packet, const void *data, size_t nbytes,
3373 packet_hdl_t *newpacket, door_cred_t *cred)
3374 {
3375 int ret;
3376 format_t fru_format;
3377 hash_obj_t *hash_obj;
3378
3379 hash_obj = lookup_handle_object(packet, PACKET_TYPE);
3380 if (hash_obj == NULL) {
3381 return (-1);
3382 }
3383
3384 hash_obj = get_container_hash_object(PACKET_TYPE,
3385 hash_obj->u.pkt_obj->segment_hdl);
3386 if (hash_obj == NULL) {
3387 return (-1);
3388 }
3389 fru_format = hash_obj->u.cont_obj->format;
3390 ret = fruaccess_func[fru_format.format - 1].update_payload(packet, data,
3391 nbytes, newpacket, cred);
3392 return (ret);
3393 }
3394
3395 int
fru_append_packet(segment_hdl_t segment,packet_t * packet,const void * payload,size_t nbytes,segment_hdl_t * newsegment,door_cred_t * cred)3396 fru_append_packet(segment_hdl_t segment, packet_t *packet,
3397 const void *payload, size_t nbytes, segment_hdl_t *newsegment,
3398 door_cred_t *cred)
3399 {
3400 int ret;
3401 format_t fru_format;
3402 hash_obj_t *hash_obj;
3403
3404 hash_obj = get_container_hash_object(PACKET_TYPE, segment);
3405 if (hash_obj == NULL) {
3406 return (-1);
3407 }
3408 fru_format = hash_obj->u.cont_obj->format;
3409
3410 ret = fruaccess_func[fru_format.format - 1].append_packet(segment,
3411 packet, payload, nbytes, newsegment, cred);
3412 return (ret);
3413 }
3414
3415 int
fru_delete_packet(packet_hdl_t packet,segment_hdl_t * newsegment,door_cred_t * cred)3416 fru_delete_packet(packet_hdl_t packet, segment_hdl_t *newsegment,
3417 door_cred_t *cred)
3418 {
3419 int ret;
3420 format_t fru_format;
3421 hash_obj_t *hash_obj;
3422
3423 hash_obj = lookup_handle_object(packet, PACKET_TYPE);
3424 if (hash_obj == NULL) {
3425 return (-1);
3426 }
3427
3428 hash_obj = get_container_hash_object(PACKET_TYPE,
3429 hash_obj->u.pkt_obj->segment_hdl);
3430 if (hash_obj == NULL) {
3431 return (-1);
3432 }
3433 fru_format = hash_obj->u.cont_obj->format;
3434
3435 ret = fruaccess_func[fru_format.format - 1].delete_packet(packet,
3436 newsegment, cred);
3437 return (ret);
3438 }
3439