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)) { \
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 PRIVATE cp_grant_t
*grants
= NULL
;
41 PRIVATE
int ngrants
= 0;
46 /* Grow the grants table if possible. */
47 cp_grant_t
*new_grants
;
51 new_size
= (1+ngrants
)*2;
52 assert(new_size
> ngrants
);
54 /* Allocate a block of new size. */
55 if(!(new_grants
=malloc(new_size
* sizeof(grants
[0]))))
58 /* Copy old block to new block. */
59 if(grants
&& ngrants
> 0)
60 memcpy(new_grants
, grants
, ngrants
* sizeof(grants
[0]));
62 /* Make sure new slots are marked unused (CPF_USED is clear). */
63 for(g
= ngrants
; g
< new_size
; g
++)
64 new_grants
[g
].cp_flags
= 0;
66 /* Inform kernel about new size (and possibly new location). */
67 if((sys_setgrant(new_grants
, new_size
))) {
69 return; /* Failed - don't grow then. */
72 /* Update internal data. */
73 if(grants
&& ngrants
> 0) free(grants
);
79 cpf_new_grantslot(void)
81 /* Find a new, free grant slot in the grant table, grow it if
82 * necessary. If no free slot is found and the grow failed,
83 * return -1. Otherwise, return grant slot number.
88 for(g
= 0; g
< ngrants
&& (grants
[g
].cp_flags
& CPF_USED
); g
++)
93 /* No free slot found? */
96 assert(g
<= ngrants
); /* ngrants can't shrink. */
98 /* ngrants hasn't increased. */
104 /* Basic sanity checks - if we get this far, g must be a valid,
107 assert(GRANT_VALID(g
));
110 assert(!(grants
[g
].cp_flags
& CPF_USED
));
116 cpf_grant_direct(endpoint_t who_to
, vir_bytes addr
, size_t bytes
, int access
)
121 /* Get new slot to put new grant in. */
122 if((g
= cpf_new_grantslot()) < 0)
125 assert(GRANT_VALID(g
));
128 assert(!(grants
[g
].cp_flags
& CPF_USED
));
130 if((r
=cpf_setgrant_direct(g
, who_to
, addr
, bytes
, access
)) < 0) {
132 return GRANT_INVALID
;
139 cpf_grant_indirect(endpoint_t who_to
, endpoint_t who_from
, cp_grant_id_t gr
)
141 /* Grant process A access into process B. B has granted us access as grant
147 /* Obtain new slot. */
148 if((g
= cpf_new_grantslot()) < 0)
151 /* Basic sanity checks. */
152 assert(GRANT_VALID(g
));
155 assert(!(grants
[g
].cp_flags
& CPF_USED
));
157 /* Fill in new slot data. */
158 if((r
=cpf_setgrant_indirect(g
, who_to
, who_from
, gr
)) < 0) {
160 return GRANT_INVALID
;
167 cpf_grant_magic(endpoint_t who_to
, endpoint_t who_from
,
168 vir_bytes addr
, size_t bytes
, int access
)
170 /* Grant process A access into process B. Not everyone can do this. */
174 ACCESS_CHECK(access
);
176 /* Obtain new slot. */
177 if((g
= cpf_new_grantslot()) < 0)
180 /* Basic sanity checks. */
181 assert(GRANT_VALID(g
));
184 assert(!(grants
[g
].cp_flags
& CPF_USED
));
186 if((r
=cpf_setgrant_magic(g
, who_to
, who_from
, addr
,
187 bytes
, access
)) < 0) {
196 cpf_revoke(cp_grant_id_t g
)
198 /* Revoke previously granted access, identified by grant id. */
201 /* Make grant invalid by setting flags to 0, clearing CPF_USED.
202 * This invalidates the grant.
204 grants
[g
].cp_flags
= 0;
210 cpf_lookup(cp_grant_id_t g
, endpoint_t
*granter
, endpoint_t
*grantee
)
212 /* First check slot validity, and if it's in use currently. */
215 if(grants
[g
].cp_flags
& CPF_DIRECT
) {
216 if(granter
) *granter
= SELF
;
217 if(grantee
) *grantee
= grants
[g
].cp_u
.cp_direct
.cp_who_to
;
218 } else if(grants
[g
].cp_flags
& CPF_MAGIC
) {
219 if(granter
) *granter
= grants
[g
].cp_u
.cp_magic
.cp_who_from
;
220 if(grantee
) *grantee
= grants
[g
].cp_u
.cp_magic
.cp_who_to
;
227 cpf_getgrants(grant_ids
, n
)
228 cp_grant_id_t
*grant_ids
;
234 for(i
= 0; i
< n
; i
++) {
235 if((grant_ids
[i
] = cpf_new_grantslot()) < 0)
237 grants
[grant_ids
[i
]].cp_flags
= CPF_USED
;
240 /* return however many grants were assigned. */
245 cpf_setgrant_direct(gid
, who
, addr
, bytes
, access
)
253 ACCESS_CHECK(access
);
255 grants
[gid
].cp_flags
= access
| CPF_DIRECT
| CPF_USED
| CPF_VALID
;
256 grants
[gid
].cp_u
.cp_direct
.cp_who_to
= who
;
257 grants
[gid
].cp_u
.cp_direct
.cp_start
= addr
;
258 grants
[gid
].cp_u
.cp_direct
.cp_len
= bytes
;
264 cpf_setgrant_indirect(gid
, who_to
, who_from
, his_gid
)
266 endpoint_t who_to
, who_from
;
267 cp_grant_id_t his_gid
;
271 /* Fill in new slot data. */
272 grants
[gid
].cp_flags
= CPF_USED
| CPF_INDIRECT
| CPF_VALID
;
273 grants
[gid
].cp_u
.cp_indirect
.cp_who_to
= who_to
;
274 grants
[gid
].cp_u
.cp_indirect
.cp_who_from
= who_from
;
275 grants
[gid
].cp_u
.cp_indirect
.cp_grant
= his_gid
;
281 cpf_setgrant_magic(gid
, who_to
, who_from
, addr
, bytes
, access
)
283 endpoint_t who_to
, who_from
;
289 ACCESS_CHECK(access
);
291 /* Fill in new slot data. */
292 grants
[gid
].cp_flags
= CPF_USED
| CPF_MAGIC
| CPF_VALID
| access
;
293 grants
[gid
].cp_u
.cp_magic
.cp_who_to
= who_to
;
294 grants
[gid
].cp_u
.cp_magic
.cp_who_from
= who_from
;
295 grants
[gid
].cp_u
.cp_magic
.cp_start
= addr
;
296 grants
[gid
].cp_u
.cp_magic
.cp_len
= bytes
;
302 cpf_setgrant_disable(gid
)
307 /* Grant is now no longer valid, but still in use. */
308 grants
[gid
].cp_flags
= CPF_USED
;