1 /*
2  * Copyright (c) 2019, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <common/debug.h>
9 #include <lib/debugfs.h>
10 
11 #include "blobs.h"
12 #include "dev.h"
13 
14 /*******************************************************************************
15  * This array contains the directories available from the root directory.
16  ******************************************************************************/
17 static const dirtab_t dirtab[] = {
18 	{"dev",   CHDIR | DEV_ROOT_QDEV,   0, O_READ},
19 	{"blobs", CHDIR | DEV_ROOT_QBLOBS, 0, O_READ},
20 	{"fip",   CHDIR | DEV_ROOT_QFIP,   0, O_READ}
21 };
22 
23 static const dirtab_t devfstab[] = {
24 };
25 
26 /*******************************************************************************
27  * This function exposes the elements of the root directory.
28  * It also exposes the content of the dev and blobs directories.
29  ******************************************************************************/
rootgen(chan_t * channel,const dirtab_t * tab,int ntab,int n,dir_t * dir)30 static int rootgen(chan_t *channel, const dirtab_t *tab, int ntab,
31 		   int n, dir_t *dir)
32 {
33 	switch (channel->qid & ~CHDIR) {
34 	case DEV_ROOT_QROOT:
35 		tab = dirtab;
36 		ntab = NELEM(dirtab);
37 		break;
38 	case DEV_ROOT_QDEV:
39 		tab = devfstab;
40 		ntab = NELEM(devfstab);
41 		break;
42 	case DEV_ROOT_QBLOBS:
43 		tab = blobtab;
44 		ntab = NELEM(blobtab);
45 		break;
46 	default:
47 		return 0;
48 	}
49 
50 	return devgen(channel, tab, ntab, n, dir);
51 }
52 
rootwalk(chan_t * channel,const char * name)53 static int rootwalk(chan_t *channel, const char *name)
54 {
55 	return devwalk(channel, name, NULL, 0, rootgen);
56 }
57 
58 /*******************************************************************************
59  * This function copies at most n bytes from the element referred by c into buf.
60  ******************************************************************************/
rootread(chan_t * channel,void * buf,int size)61 static int rootread(chan_t *channel, void *buf, int size)
62 {
63 	const dirtab_t *dp;
64 	dir_t *dir;
65 
66 	if ((channel->qid & CHDIR) != 0) {
67 		if (size < sizeof(dir_t)) {
68 			return -1;
69 		}
70 
71 		dir = buf;
72 		return dirread(channel, dir, NULL, 0, rootgen);
73 	}
74 
75 	/* Only makes sense when using debug language */
76 	assert(channel->qid != DEV_ROOT_QBLOBCTL);
77 
78 	dp = &blobtab[channel->qid - DEV_ROOT_QBLOBCTL];
79 	return buf_to_channel(channel, buf, dp->data, size, dp->length);
80 }
81 
rootstat(chan_t * channel,const char * file,dir_t * dir)82 static int rootstat(chan_t *channel, const char *file, dir_t *dir)
83 {
84 	return devstat(channel, file, dir, NULL, 0, rootgen);
85 }
86 
87 const dev_t rootdevtab = {
88 	.id = '/',
89 	.stat = rootstat,
90 	.clone = devclone,
91 	.attach = devattach,
92 	.walk = rootwalk,
93 	.read = rootread,
94 	.write = deverrwrite,
95 	.mount = deverrmount,
96 	.seek = devseek
97 };
98