diff options
-rw-r--r-- | drivers/scsi/osd/osd_initiator.c | 579 | ||||
-rw-r--r-- | include/scsi/osd_attributes.h | 327 |
2 files changed, 906 insertions, 0 deletions
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 0e6d906f1113..b982d767bf99 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c | |||
@@ -45,6 +45,10 @@ | |||
45 | 45 | ||
46 | #include "osd_debug.h" | 46 | #include "osd_debug.h" |
47 | 47 | ||
48 | #ifndef __unused | ||
49 | # define __unused __attribute__((unused)) | ||
50 | #endif | ||
51 | |||
48 | enum { OSD_REQ_RETRIES = 1 }; | 52 | enum { OSD_REQ_RETRIES = 1 }; |
49 | 53 | ||
50 | MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>"); | 54 | MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>"); |
@@ -63,6 +67,50 @@ static unsigned _osd_req_cdb_len(struct osd_request *or) | |||
63 | return OSDv1_TOTAL_CDB_LEN; | 67 | return OSDv1_TOTAL_CDB_LEN; |
64 | } | 68 | } |
65 | 69 | ||
70 | static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len) | ||
71 | { | ||
72 | return osdv1_attr_list_elem_size(len); | ||
73 | } | ||
74 | |||
75 | static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head) | ||
76 | { | ||
77 | return osdv1_list_size(list_head); | ||
78 | } | ||
79 | |||
80 | static unsigned _osd_req_sizeof_alist_header(struct osd_request *or) | ||
81 | { | ||
82 | return sizeof(struct osdv1_attributes_list_header); | ||
83 | } | ||
84 | |||
85 | static void _osd_req_set_alist_type(struct osd_request *or, | ||
86 | void *list, int list_type) | ||
87 | { | ||
88 | struct osdv1_attributes_list_header *attr_list = list; | ||
89 | |||
90 | memset(attr_list, 0, sizeof(*attr_list)); | ||
91 | attr_list->type = list_type; | ||
92 | } | ||
93 | |||
94 | static bool _osd_req_is_alist_type(struct osd_request *or, | ||
95 | void *list, int list_type) | ||
96 | { | ||
97 | if (!list) | ||
98 | return false; | ||
99 | |||
100 | if (1) { | ||
101 | struct osdv1_attributes_list_header *attr_list = list; | ||
102 | |||
103 | return attr_list->type == list_type; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | static osd_cdb_offset osd_req_encode_offset(struct osd_request *or, | ||
108 | u64 offset, unsigned *padding) | ||
109 | { | ||
110 | return __osd_encode_offset(offset, padding, | ||
111 | OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT); | ||
112 | } | ||
113 | |||
66 | void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device) | 114 | void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device) |
67 | { | 115 | { |
68 | memset(osdd, 0, sizeof(*osdd)); | 116 | memset(osdd, 0, sizeof(*osdd)); |
@@ -125,10 +173,25 @@ static void _abort_unexecuted_bios(struct request *rq) | |||
125 | } | 173 | } |
126 | } | 174 | } |
127 | 175 | ||
176 | static void _osd_free_seg(struct osd_request *or __unused, | ||
177 | struct _osd_req_data_segment *seg) | ||
178 | { | ||
179 | if (!seg->buff || !seg->alloc_size) | ||
180 | return; | ||
181 | |||
182 | kfree(seg->buff); | ||
183 | seg->buff = NULL; | ||
184 | seg->alloc_size = 0; | ||
185 | } | ||
186 | |||
128 | void osd_end_request(struct osd_request *or) | 187 | void osd_end_request(struct osd_request *or) |
129 | { | 188 | { |
130 | struct request *rq = or->request; | 189 | struct request *rq = or->request; |
131 | 190 | ||
191 | _osd_free_seg(or, &or->set_attr); | ||
192 | _osd_free_seg(or, &or->enc_get_attr); | ||
193 | _osd_free_seg(or, &or->get_attr); | ||
194 | |||
132 | if (rq) { | 195 | if (rq) { |
133 | if (rq->next_rq) { | 196 | if (rq->next_rq) { |
134 | _abort_unexecuted_bios(rq->next_rq); | 197 | _abort_unexecuted_bios(rq->next_rq); |
@@ -176,6 +239,54 @@ int osd_execute_request_async(struct osd_request *or, | |||
176 | } | 239 | } |
177 | EXPORT_SYMBOL(osd_execute_request_async); | 240 | EXPORT_SYMBOL(osd_execute_request_async); |
178 | 241 | ||
242 | u8 sg_out_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT]; | ||
243 | u8 sg_in_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT]; | ||
244 | |||
245 | static int _osd_realloc_seg(struct osd_request *or, | ||
246 | struct _osd_req_data_segment *seg, unsigned max_bytes) | ||
247 | { | ||
248 | void *buff; | ||
249 | |||
250 | if (seg->alloc_size >= max_bytes) | ||
251 | return 0; | ||
252 | |||
253 | buff = krealloc(seg->buff, max_bytes, or->alloc_flags); | ||
254 | if (!buff) { | ||
255 | OSD_ERR("Failed to Realloc %d-bytes was-%d\n", max_bytes, | ||
256 | seg->alloc_size); | ||
257 | return -ENOMEM; | ||
258 | } | ||
259 | |||
260 | memset(buff + seg->alloc_size, 0, max_bytes - seg->alloc_size); | ||
261 | seg->buff = buff; | ||
262 | seg->alloc_size = max_bytes; | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static int _alloc_set_attr_list(struct osd_request *or, | ||
267 | const struct osd_attr *oa, unsigned nelem, unsigned add_bytes) | ||
268 | { | ||
269 | unsigned total_bytes = add_bytes; | ||
270 | |||
271 | for (; nelem; --nelem, ++oa) | ||
272 | total_bytes += _osd_req_alist_elem_size(or, oa->len); | ||
273 | |||
274 | OSD_DEBUG("total_bytes=%d\n", total_bytes); | ||
275 | return _osd_realloc_seg(or, &or->set_attr, total_bytes); | ||
276 | } | ||
277 | |||
278 | static int _alloc_get_attr_desc(struct osd_request *or, unsigned max_bytes) | ||
279 | { | ||
280 | OSD_DEBUG("total_bytes=%d\n", max_bytes); | ||
281 | return _osd_realloc_seg(or, &or->enc_get_attr, max_bytes); | ||
282 | } | ||
283 | |||
284 | static int _alloc_get_attr_list(struct osd_request *or) | ||
285 | { | ||
286 | OSD_DEBUG("total_bytes=%d\n", or->get_attr.total_bytes); | ||
287 | return _osd_realloc_seg(or, &or->get_attr, or->get_attr.total_bytes); | ||
288 | } | ||
289 | |||
179 | /* | 290 | /* |
180 | * Common to all OSD commands | 291 | * Common to all OSD commands |
181 | */ | 292 | */ |
@@ -284,6 +395,410 @@ void osd_req_read(struct osd_request *or, | |||
284 | } | 395 | } |
285 | EXPORT_SYMBOL(osd_req_read); | 396 | EXPORT_SYMBOL(osd_req_read); |
286 | 397 | ||
398 | void osd_req_get_attributes(struct osd_request *or, | ||
399 | const struct osd_obj_id *obj) | ||
400 | { | ||
401 | _osd_req_encode_common(or, OSD_ACT_GET_ATTRIBUTES, obj, 0, 0); | ||
402 | } | ||
403 | EXPORT_SYMBOL(osd_req_get_attributes); | ||
404 | |||
405 | void osd_req_set_attributes(struct osd_request *or, | ||
406 | const struct osd_obj_id *obj) | ||
407 | { | ||
408 | _osd_req_encode_common(or, OSD_ACT_SET_ATTRIBUTES, obj, 0, 0); | ||
409 | } | ||
410 | EXPORT_SYMBOL(osd_req_set_attributes); | ||
411 | |||
412 | /* | ||
413 | * Attributes List-mode | ||
414 | */ | ||
415 | |||
416 | int osd_req_add_set_attr_list(struct osd_request *or, | ||
417 | const struct osd_attr *oa, unsigned nelem) | ||
418 | { | ||
419 | unsigned total_bytes = or->set_attr.total_bytes; | ||
420 | void *attr_last; | ||
421 | int ret; | ||
422 | |||
423 | if (or->attributes_mode && | ||
424 | or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) { | ||
425 | WARN_ON(1); | ||
426 | return -EINVAL; | ||
427 | } | ||
428 | or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS; | ||
429 | |||
430 | if (!total_bytes) { /* first-time: allocate and put list header */ | ||
431 | total_bytes = _osd_req_sizeof_alist_header(or); | ||
432 | ret = _alloc_set_attr_list(or, oa, nelem, total_bytes); | ||
433 | if (ret) | ||
434 | return ret; | ||
435 | _osd_req_set_alist_type(or, or->set_attr.buff, | ||
436 | OSD_ATTR_LIST_SET_RETRIEVE); | ||
437 | } | ||
438 | attr_last = or->set_attr.buff + total_bytes; | ||
439 | |||
440 | for (; nelem; --nelem) { | ||
441 | struct osd_attributes_list_element *attr; | ||
442 | unsigned elem_size = _osd_req_alist_elem_size(or, oa->len); | ||
443 | |||
444 | total_bytes += elem_size; | ||
445 | if (unlikely(or->set_attr.alloc_size < total_bytes)) { | ||
446 | or->set_attr.total_bytes = total_bytes - elem_size; | ||
447 | ret = _alloc_set_attr_list(or, oa, nelem, total_bytes); | ||
448 | if (ret) | ||
449 | return ret; | ||
450 | attr_last = | ||
451 | or->set_attr.buff + or->set_attr.total_bytes; | ||
452 | } | ||
453 | |||
454 | attr = attr_last; | ||
455 | attr->attr_page = cpu_to_be32(oa->attr_page); | ||
456 | attr->attr_id = cpu_to_be32(oa->attr_id); | ||
457 | attr->attr_bytes = cpu_to_be16(oa->len); | ||
458 | memcpy(attr->attr_val, oa->val_ptr, oa->len); | ||
459 | |||
460 | attr_last += elem_size; | ||
461 | ++oa; | ||
462 | } | ||
463 | |||
464 | or->set_attr.total_bytes = total_bytes; | ||
465 | return 0; | ||
466 | } | ||
467 | EXPORT_SYMBOL(osd_req_add_set_attr_list); | ||
468 | |||
469 | static int _append_map_kern(struct request *req, | ||
470 | void *buff, unsigned len, gfp_t flags) | ||
471 | { | ||
472 | struct bio *bio; | ||
473 | int ret; | ||
474 | |||
475 | bio = bio_map_kern(req->q, buff, len, flags); | ||
476 | if (IS_ERR(bio)) { | ||
477 | OSD_ERR("Failed bio_map_kern(%p, %d) => %ld\n", buff, len, | ||
478 | PTR_ERR(bio)); | ||
479 | return PTR_ERR(bio); | ||
480 | } | ||
481 | ret = blk_rq_append_bio(req->q, req, bio); | ||
482 | if (ret) { | ||
483 | OSD_ERR("Failed blk_rq_append_bio(%p) => %d\n", bio, ret); | ||
484 | bio_put(bio); | ||
485 | } | ||
486 | return ret; | ||
487 | } | ||
488 | |||
489 | static int _req_append_segment(struct osd_request *or, | ||
490 | unsigned padding, struct _osd_req_data_segment *seg, | ||
491 | struct _osd_req_data_segment *last_seg, struct _osd_io_info *io) | ||
492 | { | ||
493 | void *pad_buff; | ||
494 | int ret; | ||
495 | |||
496 | if (padding) { | ||
497 | /* check if we can just add it to last buffer */ | ||
498 | if (last_seg && | ||
499 | (padding <= last_seg->alloc_size - last_seg->total_bytes)) | ||
500 | pad_buff = last_seg->buff + last_seg->total_bytes; | ||
501 | else | ||
502 | pad_buff = io->pad_buff; | ||
503 | |||
504 | ret = _append_map_kern(io->req, pad_buff, padding, | ||
505 | or->alloc_flags); | ||
506 | if (ret) | ||
507 | return ret; | ||
508 | io->total_bytes += padding; | ||
509 | } | ||
510 | |||
511 | ret = _append_map_kern(io->req, seg->buff, seg->total_bytes, | ||
512 | or->alloc_flags); | ||
513 | if (ret) | ||
514 | return ret; | ||
515 | |||
516 | io->total_bytes += seg->total_bytes; | ||
517 | OSD_DEBUG("padding=%d buff=%p total_bytes=%d\n", padding, seg->buff, | ||
518 | seg->total_bytes); | ||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | static int _osd_req_finalize_set_attr_list(struct osd_request *or) | ||
523 | { | ||
524 | struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb); | ||
525 | unsigned padding; | ||
526 | int ret; | ||
527 | |||
528 | if (!or->set_attr.total_bytes) { | ||
529 | cdbh->attrs_list.set_attr_offset = OSD_OFFSET_UNUSED; | ||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | cdbh->attrs_list.set_attr_bytes = cpu_to_be32(or->set_attr.total_bytes); | ||
534 | cdbh->attrs_list.set_attr_offset = | ||
535 | osd_req_encode_offset(or, or->out.total_bytes, &padding); | ||
536 | |||
537 | ret = _req_append_segment(or, padding, &or->set_attr, | ||
538 | or->out.last_seg, &or->out); | ||
539 | if (ret) | ||
540 | return ret; | ||
541 | |||
542 | or->out.last_seg = &or->set_attr; | ||
543 | return 0; | ||
544 | } | ||
545 | |||
546 | int osd_req_add_get_attr_list(struct osd_request *or, | ||
547 | const struct osd_attr *oa, unsigned nelem) | ||
548 | { | ||
549 | unsigned total_bytes = or->enc_get_attr.total_bytes; | ||
550 | void *attr_last; | ||
551 | int ret; | ||
552 | |||
553 | if (or->attributes_mode && | ||
554 | or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) { | ||
555 | WARN_ON(1); | ||
556 | return -EINVAL; | ||
557 | } | ||
558 | or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS; | ||
559 | |||
560 | /* first time calc data-in list header size */ | ||
561 | if (!or->get_attr.total_bytes) | ||
562 | or->get_attr.total_bytes = _osd_req_sizeof_alist_header(or); | ||
563 | |||
564 | /* calc data-out info */ | ||
565 | if (!total_bytes) { /* first-time: allocate and put list header */ | ||
566 | unsigned max_bytes; | ||
567 | |||
568 | total_bytes = _osd_req_sizeof_alist_header(or); | ||
569 | max_bytes = total_bytes + | ||
570 | nelem * sizeof(struct osd_attributes_list_attrid); | ||
571 | ret = _alloc_get_attr_desc(or, max_bytes); | ||
572 | if (ret) | ||
573 | return ret; | ||
574 | |||
575 | _osd_req_set_alist_type(or, or->enc_get_attr.buff, | ||
576 | OSD_ATTR_LIST_GET); | ||
577 | } | ||
578 | attr_last = or->enc_get_attr.buff + total_bytes; | ||
579 | |||
580 | for (; nelem; --nelem) { | ||
581 | struct osd_attributes_list_attrid *attrid; | ||
582 | const unsigned cur_size = sizeof(*attrid); | ||
583 | |||
584 | total_bytes += cur_size; | ||
585 | if (unlikely(or->enc_get_attr.alloc_size < total_bytes)) { | ||
586 | or->enc_get_attr.total_bytes = total_bytes - cur_size; | ||
587 | ret = _alloc_get_attr_desc(or, | ||
588 | total_bytes + nelem * sizeof(*attrid)); | ||
589 | if (ret) | ||
590 | return ret; | ||
591 | attr_last = or->enc_get_attr.buff + | ||
592 | or->enc_get_attr.total_bytes; | ||
593 | } | ||
594 | |||
595 | attrid = attr_last; | ||
596 | attrid->attr_page = cpu_to_be32(oa->attr_page); | ||
597 | attrid->attr_id = cpu_to_be32(oa->attr_id); | ||
598 | |||
599 | attr_last += cur_size; | ||
600 | |||
601 | /* calc data-in size */ | ||
602 | or->get_attr.total_bytes += | ||
603 | _osd_req_alist_elem_size(or, oa->len); | ||
604 | ++oa; | ||
605 | } | ||
606 | |||
607 | or->enc_get_attr.total_bytes = total_bytes; | ||
608 | |||
609 | OSD_DEBUG( | ||
610 | "get_attr.total_bytes=%u(%u) enc_get_attr.total_bytes=%u(%Zu)\n", | ||
611 | or->get_attr.total_bytes, | ||
612 | or->get_attr.total_bytes - _osd_req_sizeof_alist_header(or), | ||
613 | or->enc_get_attr.total_bytes, | ||
614 | (or->enc_get_attr.total_bytes - _osd_req_sizeof_alist_header(or)) | ||
615 | / sizeof(struct osd_attributes_list_attrid)); | ||
616 | |||
617 | return 0; | ||
618 | } | ||
619 | EXPORT_SYMBOL(osd_req_add_get_attr_list); | ||
620 | |||
621 | static int _osd_req_finalize_get_attr_list(struct osd_request *or) | ||
622 | { | ||
623 | struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb); | ||
624 | unsigned out_padding; | ||
625 | unsigned in_padding; | ||
626 | int ret; | ||
627 | |||
628 | if (!or->enc_get_attr.total_bytes) { | ||
629 | cdbh->attrs_list.get_attr_desc_offset = OSD_OFFSET_UNUSED; | ||
630 | cdbh->attrs_list.get_attr_offset = OSD_OFFSET_UNUSED; | ||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | ret = _alloc_get_attr_list(or); | ||
635 | if (ret) | ||
636 | return ret; | ||
637 | |||
638 | /* The out-going buffer info update */ | ||
639 | OSD_DEBUG("out-going\n"); | ||
640 | cdbh->attrs_list.get_attr_desc_bytes = | ||
641 | cpu_to_be32(or->enc_get_attr.total_bytes); | ||
642 | |||
643 | cdbh->attrs_list.get_attr_desc_offset = | ||
644 | osd_req_encode_offset(or, or->out.total_bytes, &out_padding); | ||
645 | |||
646 | ret = _req_append_segment(or, out_padding, &or->enc_get_attr, | ||
647 | or->out.last_seg, &or->out); | ||
648 | if (ret) | ||
649 | return ret; | ||
650 | or->out.last_seg = &or->enc_get_attr; | ||
651 | |||
652 | /* The incoming buffer info update */ | ||
653 | OSD_DEBUG("in-coming\n"); | ||
654 | cdbh->attrs_list.get_attr_alloc_length = | ||
655 | cpu_to_be32(or->get_attr.total_bytes); | ||
656 | |||
657 | cdbh->attrs_list.get_attr_offset = | ||
658 | osd_req_encode_offset(or, or->in.total_bytes, &in_padding); | ||
659 | |||
660 | ret = _req_append_segment(or, in_padding, &or->get_attr, NULL, | ||
661 | &or->in); | ||
662 | if (ret) | ||
663 | return ret; | ||
664 | or->in.last_seg = &or->get_attr; | ||
665 | |||
666 | return 0; | ||
667 | } | ||
668 | |||
669 | int osd_req_decode_get_attr_list(struct osd_request *or, | ||
670 | struct osd_attr *oa, int *nelem, void **iterator) | ||
671 | { | ||
672 | unsigned cur_bytes, returned_bytes; | ||
673 | int n; | ||
674 | const unsigned sizeof_attr_list = _osd_req_sizeof_alist_header(or); | ||
675 | void *cur_p; | ||
676 | |||
677 | if (!_osd_req_is_alist_type(or, or->get_attr.buff, | ||
678 | OSD_ATTR_LIST_SET_RETRIEVE)) { | ||
679 | oa->attr_page = 0; | ||
680 | oa->attr_id = 0; | ||
681 | oa->val_ptr = NULL; | ||
682 | oa->len = 0; | ||
683 | *iterator = NULL; | ||
684 | return 0; | ||
685 | } | ||
686 | |||
687 | if (*iterator) { | ||
688 | BUG_ON((*iterator < or->get_attr.buff) || | ||
689 | (or->get_attr.buff + or->get_attr.alloc_size < *iterator)); | ||
690 | cur_p = *iterator; | ||
691 | cur_bytes = (*iterator - or->get_attr.buff) - sizeof_attr_list; | ||
692 | returned_bytes = or->get_attr.total_bytes; | ||
693 | } else { /* first time decode the list header */ | ||
694 | cur_bytes = sizeof_attr_list; | ||
695 | returned_bytes = _osd_req_alist_size(or, or->get_attr.buff) + | ||
696 | sizeof_attr_list; | ||
697 | |||
698 | cur_p = or->get_attr.buff + sizeof_attr_list; | ||
699 | |||
700 | if (returned_bytes > or->get_attr.alloc_size) { | ||
701 | OSD_DEBUG("target report: space was not big enough! " | ||
702 | "Allocate=%u Needed=%u\n", | ||
703 | or->get_attr.alloc_size, | ||
704 | returned_bytes + sizeof_attr_list); | ||
705 | |||
706 | returned_bytes = | ||
707 | or->get_attr.alloc_size - sizeof_attr_list; | ||
708 | } | ||
709 | or->get_attr.total_bytes = returned_bytes; | ||
710 | } | ||
711 | |||
712 | for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) { | ||
713 | struct osd_attributes_list_element *attr = cur_p; | ||
714 | unsigned inc; | ||
715 | |||
716 | oa->len = be16_to_cpu(attr->attr_bytes); | ||
717 | inc = _osd_req_alist_elem_size(or, oa->len); | ||
718 | OSD_DEBUG("oa->len=%d inc=%d cur_bytes=%d\n", | ||
719 | oa->len, inc, cur_bytes); | ||
720 | cur_bytes += inc; | ||
721 | if (cur_bytes > returned_bytes) { | ||
722 | OSD_ERR("BAD FOOD from target. list not valid!" | ||
723 | "c=%d r=%d n=%d\n", | ||
724 | cur_bytes, returned_bytes, n); | ||
725 | oa->val_ptr = NULL; | ||
726 | break; | ||
727 | } | ||
728 | |||
729 | oa->attr_page = be32_to_cpu(attr->attr_page); | ||
730 | oa->attr_id = be32_to_cpu(attr->attr_id); | ||
731 | oa->val_ptr = attr->attr_val; | ||
732 | |||
733 | cur_p += inc; | ||
734 | ++oa; | ||
735 | } | ||
736 | |||
737 | *iterator = (returned_bytes - cur_bytes) ? cur_p : NULL; | ||
738 | *nelem = n; | ||
739 | return returned_bytes - cur_bytes; | ||
740 | } | ||
741 | EXPORT_SYMBOL(osd_req_decode_get_attr_list); | ||
742 | |||
743 | /* | ||
744 | * Attributes Page-mode | ||
745 | */ | ||
746 | |||
747 | int osd_req_add_get_attr_page(struct osd_request *or, | ||
748 | u32 page_id, void *attar_page, unsigned max_page_len, | ||
749 | const struct osd_attr *set_one_attr) | ||
750 | { | ||
751 | struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb); | ||
752 | |||
753 | if (or->attributes_mode && | ||
754 | or->attributes_mode != OSD_CDB_GET_ATTR_PAGE_SET_ONE) { | ||
755 | WARN_ON(1); | ||
756 | return -EINVAL; | ||
757 | } | ||
758 | or->attributes_mode = OSD_CDB_GET_ATTR_PAGE_SET_ONE; | ||
759 | |||
760 | or->get_attr.buff = attar_page; | ||
761 | or->get_attr.total_bytes = max_page_len; | ||
762 | |||
763 | or->set_attr.buff = set_one_attr->val_ptr; | ||
764 | or->set_attr.total_bytes = set_one_attr->len; | ||
765 | |||
766 | cdbh->attrs_page.get_attr_page = cpu_to_be32(page_id); | ||
767 | cdbh->attrs_page.get_attr_alloc_length = cpu_to_be32(max_page_len); | ||
768 | /* ocdb->attrs_page.get_attr_offset; */ | ||
769 | |||
770 | cdbh->attrs_page.set_attr_page = cpu_to_be32(set_one_attr->attr_page); | ||
771 | cdbh->attrs_page.set_attr_id = cpu_to_be32(set_one_attr->attr_id); | ||
772 | cdbh->attrs_page.set_attr_length = cpu_to_be32(set_one_attr->len); | ||
773 | /* ocdb->attrs_page.set_attr_offset; */ | ||
774 | return 0; | ||
775 | } | ||
776 | EXPORT_SYMBOL(osd_req_add_get_attr_page); | ||
777 | |||
778 | static int _osd_req_finalize_attr_page(struct osd_request *or) | ||
779 | { | ||
780 | struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb); | ||
781 | unsigned in_padding, out_padding; | ||
782 | int ret; | ||
783 | |||
784 | /* returned page */ | ||
785 | cdbh->attrs_page.get_attr_offset = | ||
786 | osd_req_encode_offset(or, or->in.total_bytes, &in_padding); | ||
787 | |||
788 | ret = _req_append_segment(or, in_padding, &or->get_attr, NULL, | ||
789 | &or->in); | ||
790 | if (ret) | ||
791 | return ret; | ||
792 | |||
793 | /* set one value */ | ||
794 | cdbh->attrs_page.set_attr_offset = | ||
795 | osd_req_encode_offset(or, or->out.total_bytes, &out_padding); | ||
796 | |||
797 | ret = _req_append_segment(or, out_padding, &or->enc_get_attr, NULL, | ||
798 | &or->out); | ||
799 | return ret; | ||
800 | } | ||
801 | |||
287 | /* | 802 | /* |
288 | * osd_finalize_request and helpers | 803 | * osd_finalize_request and helpers |
289 | */ | 804 | */ |
@@ -378,9 +893,31 @@ int osd_finalize_request(struct osd_request *or, | |||
378 | _LLU(or->in.total_bytes), or->in.req->data_len); | 893 | _LLU(or->in.total_bytes), or->in.req->data_len); |
379 | } | 894 | } |
380 | 895 | ||
896 | or->out.pad_buff = sg_out_pad_buffer; | ||
897 | or->in.pad_buff = sg_in_pad_buffer; | ||
898 | |||
381 | if (!or->attributes_mode) | 899 | if (!or->attributes_mode) |
382 | or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS; | 900 | or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS; |
383 | cdbh->command_specific_options |= or->attributes_mode; | 901 | cdbh->command_specific_options |= or->attributes_mode; |
902 | if (or->attributes_mode == OSD_CDB_GET_ATTR_PAGE_SET_ONE) { | ||
903 | ret = _osd_req_finalize_attr_page(or); | ||
904 | } else { | ||
905 | /* TODO: I think that for the GET_ATTR command these 2 should | ||
906 | * be reversed to keep them in execution order (for embeded | ||
907 | * targets with low memory footprint) | ||
908 | */ | ||
909 | ret = _osd_req_finalize_set_attr_list(or); | ||
910 | if (ret) { | ||
911 | OSD_DEBUG("_osd_req_finalize_set_attr_list failed\n"); | ||
912 | return ret; | ||
913 | } | ||
914 | |||
915 | ret = _osd_req_finalize_get_attr_list(or); | ||
916 | if (ret) { | ||
917 | OSD_DEBUG("_osd_req_finalize_get_attr_list failed\n"); | ||
918 | return ret; | ||
919 | } | ||
920 | } | ||
384 | 921 | ||
385 | or->request->cmd = or->cdb.buff; | 922 | or->request->cmd = or->cdb.buff; |
386 | or->request->cmd_len = _osd_req_cdb_len(or); | 923 | or->request->cmd_len = _osd_req_cdb_len(or); |
@@ -446,3 +983,45 @@ void osd_set_caps(struct osd_cdb *cdb, const void *caps) | |||
446 | { | 983 | { |
447 | memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN); | 984 | memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN); |
448 | } | 985 | } |
986 | |||
987 | /* | ||
988 | * Declared in osd_protocol.h | ||
989 | * 4.12.5 Data-In and Data-Out buffer offsets | ||
990 | * byte offset = mantissa * (2^(exponent+8)) | ||
991 | * Returns the smallest allowed encoded offset that contains given @offset | ||
992 | * The actual encoded offset returned is @offset + *@padding. | ||
993 | */ | ||
994 | osd_cdb_offset __osd_encode_offset( | ||
995 | u64 offset, unsigned *padding, int min_shift, int max_shift) | ||
996 | { | ||
997 | u64 try_offset = -1, mod, align; | ||
998 | osd_cdb_offset be32_offset; | ||
999 | int shift; | ||
1000 | |||
1001 | *padding = 0; | ||
1002 | if (!offset) | ||
1003 | return 0; | ||
1004 | |||
1005 | for (shift = min_shift; shift < max_shift; ++shift) { | ||
1006 | try_offset = offset >> shift; | ||
1007 | if (try_offset < (1 << OSD_OFFSET_MAX_BITS)) | ||
1008 | break; | ||
1009 | } | ||
1010 | |||
1011 | BUG_ON(shift == max_shift); | ||
1012 | |||
1013 | align = 1 << shift; | ||
1014 | mod = offset & (align - 1); | ||
1015 | if (mod) { | ||
1016 | *padding = align - mod; | ||
1017 | try_offset += 1; | ||
1018 | } | ||
1019 | |||
1020 | try_offset |= ((shift - 8) & 0xf) << 28; | ||
1021 | be32_offset = cpu_to_be32((u32)try_offset); | ||
1022 | |||
1023 | OSD_DEBUG("offset=%llu mantissa=%llu exp=%d encoded=%x pad=%d\n", | ||
1024 | _LLU(offset), _LLU(try_offset & 0x0FFFFFFF), shift, | ||
1025 | be32_offset, *padding); | ||
1026 | return be32_offset; | ||
1027 | } | ||
diff --git a/include/scsi/osd_attributes.h b/include/scsi/osd_attributes.h new file mode 100644 index 000000000000..f888a6fda073 --- /dev/null +++ b/include/scsi/osd_attributes.h | |||
@@ -0,0 +1,327 @@ | |||
1 | #ifndef __OSD_ATTRIBUTES_H__ | ||
2 | #define __OSD_ATTRIBUTES_H__ | ||
3 | |||
4 | #include "osd_protocol.h" | ||
5 | |||
6 | /* | ||
7 | * Contains types and constants that define attribute pages and attribute | ||
8 | * numbers and their data types. | ||
9 | */ | ||
10 | |||
11 | #define ATTR_SET(pg, id, l, ptr) \ | ||
12 | { .attr_page = pg, .attr_id = id, .len = l, .val_ptr = ptr } | ||
13 | |||
14 | #define ATTR_DEF(pg, id, l) ATTR_SET(pg, id, l, NULL) | ||
15 | |||
16 | /* osd-r10 4.7.3 Attributes pages */ | ||
17 | enum { | ||
18 | OSD_APAGE_OBJECT_FIRST = 0x0, | ||
19 | OSD_APAGE_OBJECT_DIRECTORY = 0, | ||
20 | OSD_APAGE_OBJECT_INFORMATION = 1, | ||
21 | OSD_APAGE_OBJECT_QUOTAS = 2, | ||
22 | OSD_APAGE_OBJECT_TIMESTAMP = 3, | ||
23 | OSD_APAGE_OBJECT_COLLECTIONS = 4, | ||
24 | OSD_APAGE_OBJECT_SECURITY = 5, | ||
25 | OSD_APAGE_OBJECT_LAST = 0x2fffffff, | ||
26 | |||
27 | OSD_APAGE_PARTITION_FIRST = 0x30000000, | ||
28 | OSD_APAGE_PARTITION_DIRECTORY = OSD_APAGE_PARTITION_FIRST + 0, | ||
29 | OSD_APAGE_PARTITION_INFORMATION = OSD_APAGE_PARTITION_FIRST + 1, | ||
30 | OSD_APAGE_PARTITION_QUOTAS = OSD_APAGE_PARTITION_FIRST + 2, | ||
31 | OSD_APAGE_PARTITION_TIMESTAMP = OSD_APAGE_PARTITION_FIRST + 3, | ||
32 | OSD_APAGE_PARTITION_SECURITY = OSD_APAGE_PARTITION_FIRST + 5, | ||
33 | OSD_APAGE_PARTITION_LAST = 0x5FFFFFFF, | ||
34 | |||
35 | OSD_APAGE_COLLECTION_FIRST = 0x60000000, | ||
36 | OSD_APAGE_COLLECTION_DIRECTORY = OSD_APAGE_COLLECTION_FIRST + 0, | ||
37 | OSD_APAGE_COLLECTION_INFORMATION = OSD_APAGE_COLLECTION_FIRST + 1, | ||
38 | OSD_APAGE_COLLECTION_TIMESTAMP = OSD_APAGE_COLLECTION_FIRST + 3, | ||
39 | OSD_APAGE_COLLECTION_SECURITY = OSD_APAGE_COLLECTION_FIRST + 5, | ||
40 | OSD_APAGE_COLLECTION_LAST = 0x8FFFFFFF, | ||
41 | |||
42 | OSD_APAGE_ROOT_FIRST = 0x90000000, | ||
43 | OSD_APAGE_ROOT_DIRECTORY = OSD_APAGE_ROOT_FIRST + 0, | ||
44 | OSD_APAGE_ROOT_INFORMATION = OSD_APAGE_ROOT_FIRST + 1, | ||
45 | OSD_APAGE_ROOT_QUOTAS = OSD_APAGE_ROOT_FIRST + 2, | ||
46 | OSD_APAGE_ROOT_TIMESTAMP = OSD_APAGE_ROOT_FIRST + 3, | ||
47 | OSD_APAGE_ROOT_SECURITY = OSD_APAGE_ROOT_FIRST + 5, | ||
48 | OSD_APAGE_ROOT_LAST = 0xBFFFFFFF, | ||
49 | |||
50 | OSD_APAGE_RESERVED_TYPE_FIRST = 0xC0000000, | ||
51 | OSD_APAGE_RESERVED_TYPE_LAST = 0xEFFFFFFF, | ||
52 | |||
53 | OSD_APAGE_COMMON_FIRST = 0xF0000000, | ||
54 | OSD_APAGE_COMMON_LAST = 0xFFFFFFFE, | ||
55 | |||
56 | OSD_APAGE_REQUEST_ALL = 0xFFFFFFFF, | ||
57 | }; | ||
58 | |||
59 | /* subcategories of attr pages within each range above */ | ||
60 | enum { | ||
61 | OSD_APAGE_STD_FIRST = 0x0, | ||
62 | OSD_APAGE_STD_DIRECTORY = 0, | ||
63 | OSD_APAGE_STD_INFORMATION = 1, | ||
64 | OSD_APAGE_STD_QUOTAS = 2, | ||
65 | OSD_APAGE_STD_TIMESTAMP = 3, | ||
66 | OSD_APAGE_STD_COLLECTIONS = 4, | ||
67 | OSD_APAGE_STD_POLICY_SECURITY = 5, | ||
68 | OSD_APAGE_STD_LAST = 0x0000007F, | ||
69 | |||
70 | OSD_APAGE_RESERVED_FIRST = 0x00000080, | ||
71 | OSD_APAGE_RESERVED_LAST = 0x00007FFF, | ||
72 | |||
73 | OSD_APAGE_OTHER_STD_FIRST = 0x00008000, | ||
74 | OSD_APAGE_OTHER_STD_LAST = 0x0000EFFF, | ||
75 | |||
76 | OSD_APAGE_PUBLIC_FIRST = 0x0000F000, | ||
77 | OSD_APAGE_PUBLIC_LAST = 0x0000FFFF, | ||
78 | |||
79 | OSD_APAGE_APP_DEFINED_FIRST = 0x00010000, | ||
80 | OSD_APAGE_APP_DEFINED_LAST = 0x1FFFFFFF, | ||
81 | |||
82 | OSD_APAGE_VENDOR_SPECIFIC_FIRST = 0x20000000, | ||
83 | OSD_APAGE_VENDOR_SPECIFIC_LAST = 0x2FFFFFFF, | ||
84 | }; | ||
85 | |||
86 | enum { | ||
87 | OSD_ATTR_PAGE_IDENTIFICATION = 0, /* in all pages 40 bytes */ | ||
88 | }; | ||
89 | |||
90 | struct page_identification { | ||
91 | u8 vendor_identification[8]; | ||
92 | u8 page_identification[32]; | ||
93 | } __packed; | ||
94 | |||
95 | struct osd_attr_page_header { | ||
96 | __be32 page_number; | ||
97 | __be32 page_length; | ||
98 | } __packed; | ||
99 | |||
100 | /* 7.1.2.8 Root Information attributes page (OSD_APAGE_ROOT_INFORMATION) */ | ||
101 | enum { | ||
102 | OSD_ATTR_RI_OSD_SYSTEM_ID = 0x3, /* 20 */ | ||
103 | OSD_ATTR_RI_VENDOR_IDENTIFICATION = 0x4, /* 8 */ | ||
104 | OSD_ATTR_RI_PRODUCT_IDENTIFICATION = 0x5, /* 16 */ | ||
105 | OSD_ATTR_RI_PRODUCT_MODEL = 0x6, /* 32 */ | ||
106 | OSD_ATTR_RI_PRODUCT_REVISION_LEVEL = 0x7, /* 4 */ | ||
107 | OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER = 0x8, /* variable */ | ||
108 | OSD_ATTR_RI_OSD_NAME = 0x9, /* variable */ | ||
109 | OSD_ATTR_RI_TOTAL_CAPACITY = 0x80, /* 8 */ | ||
110 | OSD_ATTR_RI_USED_CAPACITY = 0x81, /* 8 */ | ||
111 | OSD_ATTR_RI_NUMBER_OF_PARTITIONS = 0xC0, /* 8 */ | ||
112 | OSD_ATTR_RI_CLOCK = 0x100, /* 6 */ | ||
113 | }; | ||
114 | /* Root_Information_attributes_page does not have a get_page structure */ | ||
115 | |||
116 | /* 7.1.2.9 Partition Information attributes page | ||
117 | * (OSD_APAGE_PARTITION_INFORMATION) | ||
118 | */ | ||
119 | enum { | ||
120 | OSD_ATTR_PI_PARTITION_ID = 0x1, /* 8 */ | ||
121 | OSD_ATTR_PI_USERNAME = 0x9, /* variable */ | ||
122 | OSD_ATTR_PI_USED_CAPACITY = 0x81, /* 8 */ | ||
123 | OSD_ATTR_PI_NUMBER_OF_OBJECTS = 0xC1, /* 8 */ | ||
124 | }; | ||
125 | /* Partition Information attributes page does not have a get_page structure */ | ||
126 | |||
127 | /* 7.1.2.10 Collection Information attributes page | ||
128 | * (OSD_APAGE_COLLECTION_INFORMATION) | ||
129 | */ | ||
130 | enum { | ||
131 | OSD_ATTR_CI_PARTITION_ID = 0x1, /* 8 */ | ||
132 | OSD_ATTR_CI_COLLECTION_OBJECT_ID = 0x2, /* 8 */ | ||
133 | OSD_ATTR_CI_USERNAME = 0x9, /* variable */ | ||
134 | OSD_ATTR_CI_USED_CAPACITY = 0x81, /* 8 */ | ||
135 | }; | ||
136 | /* Collection Information attributes page does not have a get_page structure */ | ||
137 | |||
138 | /* 7.1.2.11 User Object Information attributes page | ||
139 | * (OSD_APAGE_OBJECT_INFORMATION) | ||
140 | */ | ||
141 | enum { | ||
142 | OSD_ATTR_OI_PARTITION_ID = 0x1, /* 8 */ | ||
143 | OSD_ATTR_OI_OBJECT_ID = 0x2, /* 8 */ | ||
144 | OSD_ATTR_OI_USERNAME = 0x9, /* variable */ | ||
145 | OSD_ATTR_OI_USED_CAPACITY = 0x81, /* 8 */ | ||
146 | OSD_ATTR_OI_LOGICAL_LENGTH = 0x82, /* 8 */ | ||
147 | }; | ||
148 | /* Object Information attributes page does not have a get_page structure */ | ||
149 | |||
150 | /* 7.1.2.12 Root Quotas attributes page (OSD_APAGE_ROOT_QUOTAS) */ | ||
151 | enum { | ||
152 | OSD_ATTR_RQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH = 0x1, /* 8 */ | ||
153 | OSD_ATTR_RQ_PARTITION_CAPACITY_QUOTA = 0x10001, /* 8 */ | ||
154 | OSD_ATTR_RQ_PARTITION_OBJECT_COUNT = 0x10002, /* 8 */ | ||
155 | OSD_ATTR_RQ_PARTITION_COLLECTIONS_PER_USER_OBJECT = 0x10081, /* 4 */ | ||
156 | OSD_ATTR_RQ_PARTITION_COUNT = 0x20002, /* 8 */ | ||
157 | }; | ||
158 | |||
159 | struct Root_Quotas_attributes_page { | ||
160 | struct osd_attr_page_header hdr; /* id=R+2, size=0x24 */ | ||
161 | __be64 default_maximum_user_object_length; | ||
162 | __be64 partition_capacity_quota; | ||
163 | __be64 partition_object_count; | ||
164 | __be64 partition_collections_per_user_object; | ||
165 | __be64 partition_count; | ||
166 | } __packed; | ||
167 | |||
168 | /* 7.1.2.13 Partition Quotas attributes page (OSD_APAGE_PARTITION_QUOTAS)*/ | ||
169 | enum { | ||
170 | OSD_ATTR_PQ_DEFAULT_MAXIMUM_USER_OBJECT_LENGTH = 0x1, /* 8 */ | ||
171 | OSD_ATTR_PQ_CAPACITY_QUOTA = 0x10001, /* 8 */ | ||
172 | OSD_ATTR_PQ_OBJECT_COUNT = 0x10002, /* 8 */ | ||
173 | OSD_ATTR_PQ_COLLECTIONS_PER_USER_OBJECT = 0x10081, /* 4 */ | ||
174 | }; | ||
175 | |||
176 | struct Partition_Quotas_attributes_page { | ||
177 | struct osd_attr_page_header hdr; /* id=P+2, size=0x1C */ | ||
178 | __be64 default_maximum_user_object_length; | ||
179 | __be64 capacity_quota; | ||
180 | __be64 object_count; | ||
181 | __be64 collections_per_user_object; | ||
182 | } __packed; | ||
183 | |||
184 | /* 7.1.2.14 User Object Quotas attributes page (OSD_APAGE_OBJECT_QUOTAS) */ | ||
185 | enum { | ||
186 | OSD_ATTR_OQ_MAXIMUM_LENGTH = 0x1, /* 8 */ | ||
187 | }; | ||
188 | |||
189 | struct Object_Quotas_attributes_page { | ||
190 | struct osd_attr_page_header hdr; /* id=U+2, size=0x8 */ | ||
191 | __be64 maximum_length; | ||
192 | } __packed; | ||
193 | |||
194 | /* 7.1.2.15 Root Timestamps attributes page (OSD_APAGE_ROOT_TIMESTAMP) */ | ||
195 | enum { | ||
196 | OSD_ATTR_RT_ATTRIBUTES_ACCESSED_TIME = 0x2, /* 6 */ | ||
197 | OSD_ATTR_RT_ATTRIBUTES_MODIFIED_TIME = 0x3, /* 6 */ | ||
198 | OSD_ATTR_RT_TIMESTAMP_BYPASS = 0xFFFFFFFE, /* 1 */ | ||
199 | }; | ||
200 | |||
201 | struct root_timestamps_attributes_page { | ||
202 | struct osd_attr_page_header hdr; /* id=R+3, size=0xD */ | ||
203 | struct osd_timestamp attributes_accessed_time; | ||
204 | struct osd_timestamp attributes_modified_time; | ||
205 | u8 timestamp_bypass; | ||
206 | } __packed; | ||
207 | |||
208 | /* 7.1.2.16 Partition Timestamps attributes page | ||
209 | * (OSD_APAGE_PARTITION_TIMESTAMP) | ||
210 | */ | ||
211 | enum { | ||
212 | OSD_ATTR_PT_CREATED_TIME = 0x1, /* 6 */ | ||
213 | OSD_ATTR_PT_ATTRIBUTES_ACCESSED_TIME = 0x2, /* 6 */ | ||
214 | OSD_ATTR_PT_ATTRIBUTES_MODIFIED_TIME = 0x3, /* 6 */ | ||
215 | OSD_ATTR_PT_DATA_ACCESSED_TIME = 0x4, /* 6 */ | ||
216 | OSD_ATTR_PT_DATA_MODIFIED_TIME = 0x5, /* 6 */ | ||
217 | OSD_ATTR_PT_TIMESTAMP_BYPASS = 0xFFFFFFFE, /* 1 */ | ||
218 | }; | ||
219 | |||
220 | struct partition_timestamps_attributes_page { | ||
221 | struct osd_attr_page_header hdr; /* id=P+3, size=0x1F */ | ||
222 | struct osd_timestamp created_time; | ||
223 | struct osd_timestamp attributes_accessed_time; | ||
224 | struct osd_timestamp attributes_modified_time; | ||
225 | struct osd_timestamp data_accessed_time; | ||
226 | struct osd_timestamp data_modified_time; | ||
227 | u8 timestamp_bypass; | ||
228 | } __packed; | ||
229 | |||
230 | /* 7.1.2.17/18 Collection/Object Timestamps attributes page | ||
231 | * (OSD_APAGE_COLLECTION_TIMESTAMP/OSD_APAGE_OBJECT_TIMESTAMP) | ||
232 | */ | ||
233 | enum { | ||
234 | OSD_ATTR_OT_CREATED_TIME = 0x1, /* 6 */ | ||
235 | OSD_ATTR_OT_ATTRIBUTES_ACCESSED_TIME = 0x2, /* 6 */ | ||
236 | OSD_ATTR_OT_ATTRIBUTES_MODIFIED_TIME = 0x3, /* 6 */ | ||
237 | OSD_ATTR_OT_DATA_ACCESSED_TIME = 0x4, /* 6 */ | ||
238 | OSD_ATTR_OT_DATA_MODIFIED_TIME = 0x5, /* 6 */ | ||
239 | }; | ||
240 | |||
241 | /* same for collection */ | ||
242 | struct object_timestamps_attributes_page { | ||
243 | struct osd_attr_page_header hdr; /* id=C+3/3, size=0x1E */ | ||
244 | struct osd_timestamp created_time; | ||
245 | struct osd_timestamp attributes_accessed_time; | ||
246 | struct osd_timestamp attributes_modified_time; | ||
247 | struct osd_timestamp data_accessed_time; | ||
248 | struct osd_timestamp data_modified_time; | ||
249 | } __packed; | ||
250 | |||
251 | /* 7.1.2.19 Collections attributes page */ | ||
252 | /* TBD */ | ||
253 | |||
254 | /* 7.1.2.20 Root Policy/Security attributes page (OSD_APAGE_ROOT_SECURITY) */ | ||
255 | enum { | ||
256 | OSD_ATTR_RS_DEFAULT_SECURITY_METHOD = 0x1, /* 1 */ | ||
257 | OSD_ATTR_RS_OLDEST_VALID_NONCE_LIMIT = 0x2, /* 6 */ | ||
258 | OSD_ATTR_RS_NEWEST_VALID_NONCE_LIMIT = 0x3, /* 6 */ | ||
259 | OSD_ATTR_RS_PARTITION_DEFAULT_SECURITY_METHOD = 0x6, /* 1 */ | ||
260 | OSD_ATTR_RS_SUPPORTED_SECURITY_METHODS = 0x7, /* 2 */ | ||
261 | OSD_ATTR_RS_ADJUSTABLE_CLOCK = 0x9, /* 6 */ | ||
262 | OSD_ATTR_RS_MASTER_KEY_IDENTIFIER = 0x7FFD, /* 0 or 7 */ | ||
263 | OSD_ATTR_RS_ROOT_KEY_IDENTIFIER = 0x7FFE, /* 0 or 7 */ | ||
264 | OSD_ATTR_RS_SUPPORTED_INTEGRITY_ALGORITHM_0 = 0x80000000,/* 1,(x16)*/ | ||
265 | OSD_ATTR_RS_SUPPORTED_DH_GROUP_0 = 0x80000010,/* 1,(x16)*/ | ||
266 | }; | ||
267 | |||
268 | struct root_security_attributes_page { | ||
269 | struct osd_attr_page_header hdr; /* id=R+5, size=0x3F */ | ||
270 | u8 default_security_method; | ||
271 | u8 partition_default_security_method; | ||
272 | __be16 supported_security_methods; | ||
273 | u8 mki_valid_rki_valid; | ||
274 | struct osd_timestamp oldest_valid_nonce_limit; | ||
275 | struct osd_timestamp newest_valid_nonce_limit; | ||
276 | struct osd_timestamp adjustable_clock; | ||
277 | u8 master_key_identifier[32-25]; | ||
278 | u8 root_key_identifier[39-32]; | ||
279 | u8 supported_integrity_algorithm[16]; | ||
280 | u8 supported_dh_group[16]; | ||
281 | } __packed; | ||
282 | |||
283 | /* 7.1.2.21 Partition Policy/Security attributes page | ||
284 | * (OSD_APAGE_PARTITION_SECURITY) | ||
285 | */ | ||
286 | enum { | ||
287 | OSD_ATTR_PS_DEFAULT_SECURITY_METHOD = 0x1, /* 1 */ | ||
288 | OSD_ATTR_PS_OLDEST_VALID_NONCE = 0x2, /* 6 */ | ||
289 | OSD_ATTR_PS_NEWEST_VALID_NONCE = 0x3, /* 6 */ | ||
290 | OSD_ATTR_PS_REQUEST_NONCE_LIST_DEPTH = 0x4, /* 2 */ | ||
291 | OSD_ATTR_PS_FROZEN_WORKING_KEY_BIT_MASK = 0x5, /* 2 */ | ||
292 | OSD_ATTR_PS_PARTITION_KEY_IDENTIFIER = 0x7FFF, /* 0 or 7 */ | ||
293 | OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_FIRST = 0x8000, /* 0 or 7 */ | ||
294 | OSD_ATTR_PS_WORKING_KEY_IDENTIFIER_LAST = 0x800F, /* 0 or 7 */ | ||
295 | OSD_ATTR_PS_POLICY_ACCESS_TAG = 0x40000001, /* 4 */ | ||
296 | OSD_ATTR_PS_USER_OBJECT_POLICY_ACCESS_TAG = 0x40000002, /* 4 */ | ||
297 | }; | ||
298 | |||
299 | struct partition_security_attributes_page { | ||
300 | struct osd_attr_page_header hdr; /* id=p+5, size=0x8f */ | ||
301 | u8 reserved[3]; | ||
302 | u8 default_security_method; | ||
303 | struct osd_timestamp oldest_valid_nonce; | ||
304 | struct osd_timestamp newest_valid_nonce; | ||
305 | __be16 request_nonce_list_depth; | ||
306 | __be16 frozen_working_key_bit_mask; | ||
307 | __be32 policy_access_tag; | ||
308 | __be32 user_object_policy_access_tag; | ||
309 | u8 pki_valid; | ||
310 | __be16 wki_00_0f_vld; | ||
311 | struct osd_key_identifier partition_key_identifier; | ||
312 | struct osd_key_identifier working_key_identifiers[16]; | ||
313 | } __packed; | ||
314 | |||
315 | /* 7.1.2.22/23 Collection/Object Policy-Security attributes page | ||
316 | * (OSD_APAGE_COLLECTION_SECURITY/OSD_APAGE_OBJECT_SECURITY) | ||
317 | */ | ||
318 | enum { | ||
319 | OSD_ATTR_OS_POLICY_ACCESS_TAG = 0x40000001, /* 4 */ | ||
320 | }; | ||
321 | |||
322 | struct object_security_attributes_page { | ||
323 | struct osd_attr_page_header hdr; /* id=C+5/5, size=4 */ | ||
324 | __be32 policy_access_tag; | ||
325 | } __packed; | ||
326 | |||
327 | #endif /*ndef __OSD_ATTRIBUTES_H__*/ | ||