1433d6423SLionel Sambuc
2*3ac58492SDavid van Moolenbroek #include <string.h>
3*3ac58492SDavid van Moolenbroek
4433d6423SLionel Sambuc #include "fs.h"
5433d6423SLionel Sambuc #include "file.h"
6433d6423SLionel Sambuc
7433d6423SLionel Sambuc /*===========================================================================*
8433d6423SLionel Sambuc * do_gcov_flush *
9433d6423SLionel Sambuc *===========================================================================*/
do_gcov_flush(void)10*3ac58492SDavid van Moolenbroek int do_gcov_flush(void)
11433d6423SLionel Sambuc {
12433d6423SLionel Sambuc /* A userland tool has requested the gcov data from another
13433d6423SLionel Sambuc * process (possibly vfs itself). Grant the target process
14433d6423SLionel Sambuc * access to the supplied buffer, and perform the call that
15433d6423SLionel Sambuc * makes the target copy its buffer to the caller (incl vfs
16433d6423SLionel Sambuc * itself).
17433d6423SLionel Sambuc */
18*3ac58492SDavid van Moolenbroek char label[LABEL_MAX];
19*3ac58492SDavid van Moolenbroek vir_bytes labeladdr, buf;
20*3ac58492SDavid van Moolenbroek size_t labellen, size;
21*3ac58492SDavid van Moolenbroek endpoint_t endpt;
22433d6423SLionel Sambuc cp_grant_id_t grantid;
23*3ac58492SDavid van Moolenbroek int r;
24433d6423SLionel Sambuc message m;
25433d6423SLionel Sambuc
26*3ac58492SDavid van Moolenbroek /*
27*3ac58492SDavid van Moolenbroek * Something as sensitive as system service coverage information must be
28*3ac58492SDavid van Moolenbroek * call to the target service, and so it is not impossible to deadlock the
29*3ac58492SDavid van Moolenbroek * system with this call.
30433d6423SLionel Sambuc */
31433d6423SLionel Sambuc if (!super_user) return(EPERM);
32433d6423SLionel Sambuc
33*3ac58492SDavid van Moolenbroek labeladdr = job_m_in.m_lc_vfs_gcov.label;
34*3ac58492SDavid van Moolenbroek labellen = job_m_in.m_lc_vfs_gcov.labellen;
35*3ac58492SDavid van Moolenbroek buf = job_m_in.m_lc_vfs_gcov.buf;
36*3ac58492SDavid van Moolenbroek size = job_m_in.m_lc_vfs_gcov.buflen;
37*3ac58492SDavid van Moolenbroek
38*3ac58492SDavid van Moolenbroek /* Retrieve and look up the target label. */
39*3ac58492SDavid van Moolenbroek if (labellen >= sizeof(label))
40*3ac58492SDavid van Moolenbroek return EINVAL;
41*3ac58492SDavid van Moolenbroek if ((r = sys_datacopy_wrapper(who_e, labeladdr, SELF, (vir_bytes)label,
42*3ac58492SDavid van Moolenbroek labellen)) != OK)
43*3ac58492SDavid van Moolenbroek return r;
44*3ac58492SDavid van Moolenbroek label[labellen - 1] = '\0';
45*3ac58492SDavid van Moolenbroek
46*3ac58492SDavid van Moolenbroek if ((r = ds_retrieve_label_endpt(label, &endpt)) != OK)
47*3ac58492SDavid van Moolenbroek return r;
48*3ac58492SDavid van Moolenbroek
49*3ac58492SDavid van Moolenbroek /* Hack: init is the only non-system process with a valid label. */
50*3ac58492SDavid van Moolenbroek if (endpt == INIT_PROC_NR)
51*3ac58492SDavid van Moolenbroek return ENOENT;
52433d6423SLionel Sambuc
53433d6423SLionel Sambuc /* Grant target process to requestor's buffer. */
54*3ac58492SDavid van Moolenbroek if ((grantid = cpf_grant_magic(endpt, who_e, buf, size, CPF_WRITE)) < 0) {
55433d6423SLionel Sambuc printf("VFS: gcov_flush: grant failed\n");
56433d6423SLionel Sambuc return(ENOMEM);
57433d6423SLionel Sambuc }
58433d6423SLionel Sambuc
59*3ac58492SDavid van Moolenbroek if (endpt == VFS_PROC_NR) {
60433d6423SLionel Sambuc /* Request is for VFS itself. */
61*3ac58492SDavid van Moolenbroek r = gcov_flush(VFS_PROC_NR, grantid, size);
62433d6423SLionel Sambuc } else {
63433d6423SLionel Sambuc /* Perform generic GCOV request. */
64*3ac58492SDavid van Moolenbroek memset(&m, 0, sizeof(m));
65*3ac58492SDavid van Moolenbroek m.m_vfs_lsys_gcov.grant = grantid;
66*3ac58492SDavid van Moolenbroek m.m_vfs_lsys_gcov.size = size;
67*3ac58492SDavid van Moolenbroek r = _taskcall(endpt, COMMON_REQ_GCOV_DATA, &m);
68433d6423SLionel Sambuc }
69433d6423SLionel Sambuc
70433d6423SLionel Sambuc cpf_revoke(grantid);
71433d6423SLionel Sambuc
72433d6423SLionel Sambuc return(r);
73433d6423SLionel Sambuc }
74