2 /* Library functions to maintain internal data copying tables.
4 * April 21 2006: Initial version (Ben Gras)
10 #include <minix/sysutil.h>
13 #include <minix/syslib.h>
14 #include <minix/safecopies.h>
15 #include <minix/com.h>
18 #define ACCESS_CHECK(a) { \
19 if((a) & ~(CPF_READ|CPF_WRITE|CPF_TRY)) { \
25 #define GID_CHECK(gid) { \
26 if(!GRANT_VALID(gid) || (gid) < 0 || (gid) >= ngrants) {\
32 #define GID_CHECK_USED(gid) { \
34 if(!(grants[gid].cp_flags & CPF_USED)) { \
40 #define CLICK_ALIGNMENT_CHECK(addr, bytes) { \
41 if(((vir_bytes)(addr) % CLICK_SIZE != 0) \
42 || ((vir_bytes)(bytes) % CLICK_SIZE != 0)) { \
47 #define NR_STATIC_GRANTS 2
48 static cp_grant_t static_grants
[NR_STATIC_GRANTS
];
49 static cp_grant_t
*grants
= NULL
;
50 static int ngrants
= 0;
55 /* Grow the grants table if possible. */
56 cp_grant_t
*new_grants
;
61 /* Use statically allocated grants the first time. */
62 new_size
= NR_STATIC_GRANTS
;
63 new_grants
= static_grants
;
66 new_size
= (1+ngrants
)*2;
67 assert(new_size
> ngrants
);
69 /* Allocate a block of new size. */
70 if(!(new_grants
=malloc(new_size
* sizeof(grants
[0])))) {
75 /* Copy old block to new block. */
76 if(grants
&& ngrants
> 0)
77 memcpy(new_grants
, grants
, ngrants
* sizeof(grants
[0]));
79 /* Make sure new slots are marked unused (CPF_USED is clear). */
80 for(g
= ngrants
; g
< new_size
; g
++)
81 new_grants
[g
].cp_flags
= 0;
83 /* Inform kernel about new size (and possibly new location). */
84 if((sys_setgrant(new_grants
, new_size
))) {
85 if(new_grants
!= static_grants
) free(new_grants
);
86 return; /* Failed - don't grow then. */
89 /* Update internal data. */
90 if(grants
&& ngrants
> 0 && grants
!= static_grants
) free(grants
);
96 cpf_new_grantslot(void)
98 /* Find a new, free grant slot in the grant table, grow it if
99 * necessary. If no free slot is found and the grow failed,
100 * return -1. Otherwise, return grant slot number.
104 /* Find free slot. */
105 for(g
= 0; g
< ngrants
&& (grants
[g
].cp_flags
& CPF_USED
); g
++)
108 assert(g
<= ngrants
);
110 /* No free slot found? */
113 assert(g
<= ngrants
); /* ngrants can't shrink. */
115 /* ngrants hasn't increased. */
121 /* Basic sanity checks - if we get this far, g must be a valid,
124 assert(GRANT_VALID(g
));
127 assert(!(grants
[g
].cp_flags
& CPF_USED
));
133 cpf_grant_direct(endpoint_t who_to
, vir_bytes addr
, size_t bytes
, int access
)
138 /* Get new slot to put new grant in. */
139 if((g
= cpf_new_grantslot()) < 0)
140 return(GRANT_INVALID
);
142 assert(GRANT_VALID(g
));
145 assert(!(grants
[g
].cp_flags
& CPF_USED
));
147 if((r
=cpf_setgrant_direct(g
, who_to
, addr
, bytes
, access
)) < 0) {
149 return(GRANT_INVALID
);
156 cpf_grant_indirect(endpoint_t who_to
, endpoint_t who_from
, cp_grant_id_t gr
)
158 /* Grant process A access into process B. B has granted us access as grant
164 /* Obtain new slot. */
165 if((g
= cpf_new_grantslot()) < 0)
168 /* Basic sanity checks. */
169 assert(GRANT_VALID(g
));
172 assert(!(grants
[g
].cp_flags
& CPF_USED
));
174 /* Fill in new slot data. */
175 if((r
=cpf_setgrant_indirect(g
, who_to
, who_from
, gr
)) < 0) {
177 return GRANT_INVALID
;
184 cpf_grant_magic(endpoint_t who_to
, endpoint_t who_from
,
185 vir_bytes addr
, size_t bytes
, int access
)
187 /* Grant process A access into process B. Not everyone can do this. */
191 ACCESS_CHECK(access
);
193 /* Obtain new slot. */
194 if((g
= cpf_new_grantslot()) < 0)
197 /* Basic sanity checks. */
198 assert(GRANT_VALID(g
));
201 assert(!(grants
[g
].cp_flags
& CPF_USED
));
203 if((r
=cpf_setgrant_magic(g
, who_to
, who_from
, addr
,
204 bytes
, access
)) < 0) {
213 cpf_revoke(cp_grant_id_t g
)
215 /* Revoke previously granted access, identified by grant id. */
218 /* Make grant invalid by setting flags to 0, clearing CPF_USED.
219 * This invalidates the grant.
221 grants
[g
].cp_flags
= 0;
227 cpf_lookup(cp_grant_id_t g
, endpoint_t
*granter
, endpoint_t
*grantee
)
229 /* First check slot validity, and if it's in use currently. */
232 if(grants
[g
].cp_flags
& CPF_DIRECT
) {
233 if(granter
) *granter
= SELF
;
234 if(grantee
) *grantee
= grants
[g
].cp_u
.cp_direct
.cp_who_to
;
235 } else if(grants
[g
].cp_flags
& CPF_MAGIC
) {
236 if(granter
) *granter
= grants
[g
].cp_u
.cp_magic
.cp_who_from
;
237 if(grantee
) *grantee
= grants
[g
].cp_u
.cp_magic
.cp_who_to
;
244 cpf_getgrants(cp_grant_id_t
*grant_ids
, int n
)
248 for(i
= 0; i
< n
; i
++) {
249 if((grant_ids
[i
] = cpf_new_grantslot()) < 0)
251 grants
[grant_ids
[i
]].cp_flags
= CPF_USED
;
254 /* return however many grants were assigned. */
259 cpf_setgrant_direct(gid
, who
, addr
, bytes
, access
)
267 ACCESS_CHECK(access
);
269 /* Fill in new slot data. */
270 grants
[gid
].cp_flags
= access
| CPF_DIRECT
| CPF_USED
| CPF_VALID
;
271 grants
[gid
].cp_u
.cp_direct
.cp_who_to
= who
;
272 grants
[gid
].cp_u
.cp_direct
.cp_start
= addr
;
273 grants
[gid
].cp_u
.cp_direct
.cp_len
= bytes
;
279 cpf_setgrant_indirect(gid
, who_to
, who_from
, his_gid
)
281 endpoint_t who_to
, who_from
;
282 cp_grant_id_t his_gid
;
286 /* Fill in new slot data. */
287 grants
[gid
].cp_flags
= CPF_USED
| CPF_INDIRECT
| CPF_VALID
;
288 grants
[gid
].cp_u
.cp_indirect
.cp_who_to
= who_to
;
289 grants
[gid
].cp_u
.cp_indirect
.cp_who_from
= who_from
;
290 grants
[gid
].cp_u
.cp_indirect
.cp_grant
= his_gid
;
296 cpf_setgrant_magic(gid
, who_to
, who_from
, addr
, bytes
, access
)
298 endpoint_t who_to
, who_from
;
304 ACCESS_CHECK(access
);
306 /* Fill in new slot data. */
307 grants
[gid
].cp_flags
= CPF_USED
| CPF_MAGIC
| CPF_VALID
| access
;
308 grants
[gid
].cp_u
.cp_magic
.cp_who_to
= who_to
;
309 grants
[gid
].cp_u
.cp_magic
.cp_who_from
= who_from
;
310 grants
[gid
].cp_u
.cp_magic
.cp_start
= addr
;
311 grants
[gid
].cp_u
.cp_magic
.cp_len
= bytes
;
317 cpf_setgrant_disable(gid
)
322 /* Grant is now no longer valid, but still in use. */
323 grants
[gid
].cp_flags
= CPF_USED
;
331 /* Inform the kernel about the location of the grant table. This is needed
335 sys_setgrant(grants
, ngrants
); /* Do we need error checking? */