xref: /openbmc/linux/tools/bootconfig/main.c (revision 85c46b78da58398be1c5166f55063c0512decd39)
1950313ebSMasami Hiramatsu // SPDX-License-Identifier: GPL-2.0
2950313ebSMasami Hiramatsu /*
3950313ebSMasami Hiramatsu  * Boot config tool for initrd image
4950313ebSMasami Hiramatsu  */
5950313ebSMasami Hiramatsu #include <stdio.h>
6950313ebSMasami Hiramatsu #include <stdlib.h>
7950313ebSMasami Hiramatsu #include <sys/types.h>
8950313ebSMasami Hiramatsu #include <sys/stat.h>
9950313ebSMasami Hiramatsu #include <fcntl.h>
10950313ebSMasami Hiramatsu #include <unistd.h>
11950313ebSMasami Hiramatsu #include <string.h>
12950313ebSMasami Hiramatsu #include <errno.h>
13950313ebSMasami Hiramatsu 
14950313ebSMasami Hiramatsu #include <linux/kernel.h>
15950313ebSMasami Hiramatsu #include <linux/bootconfig.h>
16950313ebSMasami Hiramatsu 
17950313ebSMasami Hiramatsu int pr_output = 1;
18950313ebSMasami Hiramatsu 
19950313ebSMasami Hiramatsu static int xbc_show_array(struct xbc_node *node)
20950313ebSMasami Hiramatsu {
21950313ebSMasami Hiramatsu 	const char *val;
22950313ebSMasami Hiramatsu 	int i = 0;
23950313ebSMasami Hiramatsu 
24950313ebSMasami Hiramatsu 	xbc_array_for_each_value(node, val) {
25950313ebSMasami Hiramatsu 		printf("\"%s\"%s", val, node->next ? ", " : ";\n");
26950313ebSMasami Hiramatsu 		i++;
27950313ebSMasami Hiramatsu 	}
28950313ebSMasami Hiramatsu 	return i;
29950313ebSMasami Hiramatsu }
30950313ebSMasami Hiramatsu 
31950313ebSMasami Hiramatsu static void xbc_show_compact_tree(void)
32950313ebSMasami Hiramatsu {
33950313ebSMasami Hiramatsu 	struct xbc_node *node, *cnode;
34950313ebSMasami Hiramatsu 	int depth = 0, i;
35950313ebSMasami Hiramatsu 
36950313ebSMasami Hiramatsu 	node = xbc_root_node();
37950313ebSMasami Hiramatsu 	while (node && xbc_node_is_key(node)) {
38950313ebSMasami Hiramatsu 		for (i = 0; i < depth; i++)
39950313ebSMasami Hiramatsu 			printf("\t");
40950313ebSMasami Hiramatsu 		cnode = xbc_node_get_child(node);
41950313ebSMasami Hiramatsu 		while (cnode && xbc_node_is_key(cnode) && !cnode->next) {
42950313ebSMasami Hiramatsu 			printf("%s.", xbc_node_get_data(node));
43950313ebSMasami Hiramatsu 			node = cnode;
44950313ebSMasami Hiramatsu 			cnode = xbc_node_get_child(node);
45950313ebSMasami Hiramatsu 		}
46950313ebSMasami Hiramatsu 		if (cnode && xbc_node_is_key(cnode)) {
47950313ebSMasami Hiramatsu 			printf("%s {\n", xbc_node_get_data(node));
48950313ebSMasami Hiramatsu 			depth++;
49950313ebSMasami Hiramatsu 			node = cnode;
50950313ebSMasami Hiramatsu 			continue;
51950313ebSMasami Hiramatsu 		} else if (cnode && xbc_node_is_value(cnode)) {
52950313ebSMasami Hiramatsu 			printf("%s = ", xbc_node_get_data(node));
53950313ebSMasami Hiramatsu 			if (cnode->next)
54950313ebSMasami Hiramatsu 				xbc_show_array(cnode);
55950313ebSMasami Hiramatsu 			else
56950313ebSMasami Hiramatsu 				printf("\"%s\";\n", xbc_node_get_data(cnode));
57950313ebSMasami Hiramatsu 		} else {
58950313ebSMasami Hiramatsu 			printf("%s;\n", xbc_node_get_data(node));
59950313ebSMasami Hiramatsu 		}
60950313ebSMasami Hiramatsu 
61950313ebSMasami Hiramatsu 		if (node->next) {
62950313ebSMasami Hiramatsu 			node = xbc_node_get_next(node);
63950313ebSMasami Hiramatsu 			continue;
64950313ebSMasami Hiramatsu 		}
65950313ebSMasami Hiramatsu 		while (!node->next) {
66950313ebSMasami Hiramatsu 			node = xbc_node_get_parent(node);
67950313ebSMasami Hiramatsu 			if (!node)
68950313ebSMasami Hiramatsu 				return;
69950313ebSMasami Hiramatsu 			if (!xbc_node_get_child(node)->next)
70950313ebSMasami Hiramatsu 				continue;
71950313ebSMasami Hiramatsu 			depth--;
72950313ebSMasami Hiramatsu 			for (i = 0; i < depth; i++)
73950313ebSMasami Hiramatsu 				printf("\t");
74950313ebSMasami Hiramatsu 			printf("}\n");
75950313ebSMasami Hiramatsu 		}
76950313ebSMasami Hiramatsu 		node = xbc_node_get_next(node);
77950313ebSMasami Hiramatsu 	}
78950313ebSMasami Hiramatsu }
79950313ebSMasami Hiramatsu 
80950313ebSMasami Hiramatsu /* Simple real checksum */
81950313ebSMasami Hiramatsu int checksum(unsigned char *buf, int len)
82950313ebSMasami Hiramatsu {
83950313ebSMasami Hiramatsu 	int i, sum = 0;
84950313ebSMasami Hiramatsu 
85950313ebSMasami Hiramatsu 	for (i = 0; i < len; i++)
86950313ebSMasami Hiramatsu 		sum += buf[i];
87950313ebSMasami Hiramatsu 
88950313ebSMasami Hiramatsu 	return sum;
89950313ebSMasami Hiramatsu }
90950313ebSMasami Hiramatsu 
91950313ebSMasami Hiramatsu #define PAGE_SIZE	4096
92950313ebSMasami Hiramatsu 
93950313ebSMasami Hiramatsu int load_xbc_fd(int fd, char **buf, int size)
94950313ebSMasami Hiramatsu {
95950313ebSMasami Hiramatsu 	int ret;
96950313ebSMasami Hiramatsu 
97950313ebSMasami Hiramatsu 	*buf = malloc(size + 1);
98950313ebSMasami Hiramatsu 	if (!*buf)
99950313ebSMasami Hiramatsu 		return -ENOMEM;
100950313ebSMasami Hiramatsu 
101950313ebSMasami Hiramatsu 	ret = read(fd, *buf, size);
102950313ebSMasami Hiramatsu 	if (ret < 0)
103950313ebSMasami Hiramatsu 		return -errno;
104950313ebSMasami Hiramatsu 	(*buf)[size] = '\0';
105950313ebSMasami Hiramatsu 
106950313ebSMasami Hiramatsu 	return ret;
107950313ebSMasami Hiramatsu }
108950313ebSMasami Hiramatsu 
109950313ebSMasami Hiramatsu /* Return the read size or -errno */
110950313ebSMasami Hiramatsu int load_xbc_file(const char *path, char **buf)
111950313ebSMasami Hiramatsu {
112950313ebSMasami Hiramatsu 	struct stat stat;
113950313ebSMasami Hiramatsu 	int fd, ret;
114950313ebSMasami Hiramatsu 
115950313ebSMasami Hiramatsu 	fd = open(path, O_RDONLY);
116950313ebSMasami Hiramatsu 	if (fd < 0)
117950313ebSMasami Hiramatsu 		return -errno;
118950313ebSMasami Hiramatsu 	ret = fstat(fd, &stat);
119950313ebSMasami Hiramatsu 	if (ret < 0)
120950313ebSMasami Hiramatsu 		return -errno;
121950313ebSMasami Hiramatsu 
122950313ebSMasami Hiramatsu 	ret = load_xbc_fd(fd, buf, stat.st_size);
123950313ebSMasami Hiramatsu 
124950313ebSMasami Hiramatsu 	close(fd);
125950313ebSMasami Hiramatsu 
126950313ebSMasami Hiramatsu 	return ret;
127950313ebSMasami Hiramatsu }
128950313ebSMasami Hiramatsu 
129950313ebSMasami Hiramatsu int load_xbc_from_initrd(int fd, char **buf)
130950313ebSMasami Hiramatsu {
131950313ebSMasami Hiramatsu 	struct stat stat;
132950313ebSMasami Hiramatsu 	int ret;
133950313ebSMasami Hiramatsu 	u32 size = 0, csum = 0, rcsum;
134*85c46b78SMasami Hiramatsu 	char magic[BOOTCONFIG_MAGIC_LEN];
135950313ebSMasami Hiramatsu 
136950313ebSMasami Hiramatsu 	ret = fstat(fd, &stat);
137950313ebSMasami Hiramatsu 	if (ret < 0)
138950313ebSMasami Hiramatsu 		return -errno;
139950313ebSMasami Hiramatsu 
140*85c46b78SMasami Hiramatsu 	if (stat.st_size < 8 + BOOTCONFIG_MAGIC_LEN)
141950313ebSMasami Hiramatsu 		return 0;
142950313ebSMasami Hiramatsu 
143*85c46b78SMasami Hiramatsu 	if (lseek(fd, -BOOTCONFIG_MAGIC_LEN, SEEK_END) < 0) {
144*85c46b78SMasami Hiramatsu 		pr_err("Failed to lseek: %d\n", -errno);
145*85c46b78SMasami Hiramatsu 		return -errno;
146*85c46b78SMasami Hiramatsu 	}
147*85c46b78SMasami Hiramatsu 	if (read(fd, magic, BOOTCONFIG_MAGIC_LEN) < 0)
148*85c46b78SMasami Hiramatsu 		return -errno;
149*85c46b78SMasami Hiramatsu 	/* Check the bootconfig magic bytes */
150*85c46b78SMasami Hiramatsu 	if (memcmp(magic, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN) != 0)
151*85c46b78SMasami Hiramatsu 		return 0;
152*85c46b78SMasami Hiramatsu 
153*85c46b78SMasami Hiramatsu 	if (lseek(fd, -(8 + BOOTCONFIG_MAGIC_LEN), SEEK_END) < 0) {
15497378001SMasami Hiramatsu 		pr_err("Failed to lseek: %d\n", -errno);
155950313ebSMasami Hiramatsu 		return -errno;
156950313ebSMasami Hiramatsu 	}
157950313ebSMasami Hiramatsu 
158950313ebSMasami Hiramatsu 	if (read(fd, &size, sizeof(u32)) < 0)
159950313ebSMasami Hiramatsu 		return -errno;
160950313ebSMasami Hiramatsu 
161950313ebSMasami Hiramatsu 	if (read(fd, &csum, sizeof(u32)) < 0)
162950313ebSMasami Hiramatsu 		return -errno;
163950313ebSMasami Hiramatsu 
164*85c46b78SMasami Hiramatsu 	/* Wrong size error  */
165*85c46b78SMasami Hiramatsu 	if (stat.st_size < size + 8 + BOOTCONFIG_MAGIC_LEN) {
166*85c46b78SMasami Hiramatsu 		pr_err("bootconfig size is too big\n");
167*85c46b78SMasami Hiramatsu 		return -E2BIG;
168*85c46b78SMasami Hiramatsu 	}
169950313ebSMasami Hiramatsu 
170*85c46b78SMasami Hiramatsu 	if (lseek(fd, stat.st_size - (size + 8 + BOOTCONFIG_MAGIC_LEN),
171*85c46b78SMasami Hiramatsu 		  SEEK_SET) < 0) {
17297378001SMasami Hiramatsu 		pr_err("Failed to lseek: %d\n", -errno);
173950313ebSMasami Hiramatsu 		return -errno;
174950313ebSMasami Hiramatsu 	}
175950313ebSMasami Hiramatsu 
176950313ebSMasami Hiramatsu 	ret = load_xbc_fd(fd, buf, size);
177950313ebSMasami Hiramatsu 	if (ret < 0)
178950313ebSMasami Hiramatsu 		return ret;
179950313ebSMasami Hiramatsu 
180*85c46b78SMasami Hiramatsu 	/* Wrong Checksum */
181950313ebSMasami Hiramatsu 	rcsum = checksum((unsigned char *)*buf, size);
182950313ebSMasami Hiramatsu 	if (csum != rcsum) {
18397378001SMasami Hiramatsu 		pr_err("checksum error: %d != %d\n", csum, rcsum);
184*85c46b78SMasami Hiramatsu 		return -EINVAL;
185950313ebSMasami Hiramatsu 	}
186950313ebSMasami Hiramatsu 
187950313ebSMasami Hiramatsu 	ret = xbc_init(*buf);
188*85c46b78SMasami Hiramatsu 	/* Wrong data */
189950313ebSMasami Hiramatsu 	if (ret < 0)
190*85c46b78SMasami Hiramatsu 		return ret;
191950313ebSMasami Hiramatsu 
192950313ebSMasami Hiramatsu 	return size;
193950313ebSMasami Hiramatsu }
194950313ebSMasami Hiramatsu 
195950313ebSMasami Hiramatsu int show_xbc(const char *path)
196950313ebSMasami Hiramatsu {
197950313ebSMasami Hiramatsu 	int ret, fd;
198950313ebSMasami Hiramatsu 	char *buf = NULL;
199950313ebSMasami Hiramatsu 
200950313ebSMasami Hiramatsu 	fd = open(path, O_RDONLY);
201950313ebSMasami Hiramatsu 	if (fd < 0) {
20297378001SMasami Hiramatsu 		pr_err("Failed to open initrd %s: %d\n", path, fd);
203950313ebSMasami Hiramatsu 		return -errno;
204950313ebSMasami Hiramatsu 	}
205950313ebSMasami Hiramatsu 
206950313ebSMasami Hiramatsu 	ret = load_xbc_from_initrd(fd, &buf);
207950313ebSMasami Hiramatsu 	if (ret < 0)
20897378001SMasami Hiramatsu 		pr_err("Failed to load a boot config from initrd: %d\n", ret);
209950313ebSMasami Hiramatsu 	else
210950313ebSMasami Hiramatsu 		xbc_show_compact_tree();
211950313ebSMasami Hiramatsu 
212950313ebSMasami Hiramatsu 	close(fd);
213950313ebSMasami Hiramatsu 	free(buf);
214950313ebSMasami Hiramatsu 
215950313ebSMasami Hiramatsu 	return ret;
216950313ebSMasami Hiramatsu }
217950313ebSMasami Hiramatsu 
218950313ebSMasami Hiramatsu int delete_xbc(const char *path)
219950313ebSMasami Hiramatsu {
220950313ebSMasami Hiramatsu 	struct stat stat;
221950313ebSMasami Hiramatsu 	int ret = 0, fd, size;
222950313ebSMasami Hiramatsu 	char *buf = NULL;
223950313ebSMasami Hiramatsu 
224950313ebSMasami Hiramatsu 	fd = open(path, O_RDWR);
225950313ebSMasami Hiramatsu 	if (fd < 0) {
22697378001SMasami Hiramatsu 		pr_err("Failed to open initrd %s: %d\n", path, fd);
227950313ebSMasami Hiramatsu 		return -errno;
228950313ebSMasami Hiramatsu 	}
229950313ebSMasami Hiramatsu 
230950313ebSMasami Hiramatsu 	/*
231950313ebSMasami Hiramatsu 	 * Suppress error messages in xbc_init() because it can be just a
232950313ebSMasami Hiramatsu 	 * data which concidentally matches the size and checksum footer.
233950313ebSMasami Hiramatsu 	 */
234950313ebSMasami Hiramatsu 	pr_output = 0;
235950313ebSMasami Hiramatsu 	size = load_xbc_from_initrd(fd, &buf);
236950313ebSMasami Hiramatsu 	pr_output = 1;
237950313ebSMasami Hiramatsu 	if (size < 0) {
238950313ebSMasami Hiramatsu 		ret = size;
23997378001SMasami Hiramatsu 		pr_err("Failed to load a boot config from initrd: %d\n", ret);
240950313ebSMasami Hiramatsu 	} else if (size > 0) {
241950313ebSMasami Hiramatsu 		ret = fstat(fd, &stat);
242950313ebSMasami Hiramatsu 		if (!ret)
243*85c46b78SMasami Hiramatsu 			ret = ftruncate(fd, stat.st_size
244*85c46b78SMasami Hiramatsu 					- size - 8 - BOOTCONFIG_MAGIC_LEN);
245950313ebSMasami Hiramatsu 		if (ret)
246950313ebSMasami Hiramatsu 			ret = -errno;
247950313ebSMasami Hiramatsu 	} /* Ignore if there is no boot config in initrd */
248950313ebSMasami Hiramatsu 
249950313ebSMasami Hiramatsu 	close(fd);
250950313ebSMasami Hiramatsu 	free(buf);
251950313ebSMasami Hiramatsu 
252950313ebSMasami Hiramatsu 	return ret;
253950313ebSMasami Hiramatsu }
254950313ebSMasami Hiramatsu 
255950313ebSMasami Hiramatsu int apply_xbc(const char *path, const char *xbc_path)
256950313ebSMasami Hiramatsu {
257950313ebSMasami Hiramatsu 	u32 size, csum;
258950313ebSMasami Hiramatsu 	char *buf, *data;
259950313ebSMasami Hiramatsu 	int ret, fd;
260950313ebSMasami Hiramatsu 
261950313ebSMasami Hiramatsu 	ret = load_xbc_file(xbc_path, &buf);
262950313ebSMasami Hiramatsu 	if (ret < 0) {
26397378001SMasami Hiramatsu 		pr_err("Failed to load %s : %d\n", xbc_path, ret);
264950313ebSMasami Hiramatsu 		return ret;
265950313ebSMasami Hiramatsu 	}
266950313ebSMasami Hiramatsu 	size = strlen(buf) + 1;
267950313ebSMasami Hiramatsu 	csum = checksum((unsigned char *)buf, size);
268950313ebSMasami Hiramatsu 
269950313ebSMasami Hiramatsu 	/* Prepare xbc_path data */
270950313ebSMasami Hiramatsu 	data = malloc(size + 8);
271950313ebSMasami Hiramatsu 	if (!data)
272950313ebSMasami Hiramatsu 		return -ENOMEM;
273950313ebSMasami Hiramatsu 	strcpy(data, buf);
274950313ebSMasami Hiramatsu 	*(u32 *)(data + size) = size;
275950313ebSMasami Hiramatsu 	*(u32 *)(data + size + 4) = csum;
276950313ebSMasami Hiramatsu 
277950313ebSMasami Hiramatsu 	/* Check the data format */
278950313ebSMasami Hiramatsu 	ret = xbc_init(buf);
279950313ebSMasami Hiramatsu 	if (ret < 0) {
28097378001SMasami Hiramatsu 		pr_err("Failed to parse %s: %d\n", xbc_path, ret);
281950313ebSMasami Hiramatsu 		free(data);
282950313ebSMasami Hiramatsu 		free(buf);
283950313ebSMasami Hiramatsu 		return ret;
284950313ebSMasami Hiramatsu 	}
285950313ebSMasami Hiramatsu 	printf("Apply %s to %s\n", xbc_path, path);
2860f0d0a77SMasami Hiramatsu 	printf("\tNumber of nodes: %d\n", ret);
287950313ebSMasami Hiramatsu 	printf("\tSize: %u bytes\n", (unsigned int)size);
288950313ebSMasami Hiramatsu 	printf("\tChecksum: %d\n", (unsigned int)csum);
289950313ebSMasami Hiramatsu 
290950313ebSMasami Hiramatsu 	/* TODO: Check the options by schema */
291950313ebSMasami Hiramatsu 	xbc_destroy_all();
292950313ebSMasami Hiramatsu 	free(buf);
293950313ebSMasami Hiramatsu 
294950313ebSMasami Hiramatsu 	/* Remove old boot config if exists */
295950313ebSMasami Hiramatsu 	ret = delete_xbc(path);
296950313ebSMasami Hiramatsu 	if (ret < 0) {
29797378001SMasami Hiramatsu 		pr_err("Failed to delete previous boot config: %d\n", ret);
298950313ebSMasami Hiramatsu 		return ret;
299950313ebSMasami Hiramatsu 	}
300950313ebSMasami Hiramatsu 
301950313ebSMasami Hiramatsu 	/* Apply new one */
302950313ebSMasami Hiramatsu 	fd = open(path, O_RDWR | O_APPEND);
303950313ebSMasami Hiramatsu 	if (fd < 0) {
30497378001SMasami Hiramatsu 		pr_err("Failed to open %s: %d\n", path, fd);
305950313ebSMasami Hiramatsu 		return fd;
306950313ebSMasami Hiramatsu 	}
307950313ebSMasami Hiramatsu 	/* TODO: Ensure the @path is initramfs/initrd image */
308950313ebSMasami Hiramatsu 	ret = write(fd, data, size + 8);
309950313ebSMasami Hiramatsu 	if (ret < 0) {
31097378001SMasami Hiramatsu 		pr_err("Failed to apply a boot config: %d\n", ret);
311950313ebSMasami Hiramatsu 		return ret;
312950313ebSMasami Hiramatsu 	}
313*85c46b78SMasami Hiramatsu 	/* Write a magic word of the bootconfig */
314*85c46b78SMasami Hiramatsu 	ret = write(fd, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN);
315*85c46b78SMasami Hiramatsu 	if (ret < 0) {
316*85c46b78SMasami Hiramatsu 		pr_err("Failed to apply a boot config magic: %d\n", ret);
317*85c46b78SMasami Hiramatsu 		return ret;
318*85c46b78SMasami Hiramatsu 	}
319950313ebSMasami Hiramatsu 	close(fd);
320950313ebSMasami Hiramatsu 	free(data);
321950313ebSMasami Hiramatsu 
322950313ebSMasami Hiramatsu 	return 0;
323950313ebSMasami Hiramatsu }
324950313ebSMasami Hiramatsu 
325950313ebSMasami Hiramatsu int usage(void)
326950313ebSMasami Hiramatsu {
327950313ebSMasami Hiramatsu 	printf("Usage: bootconfig [OPTIONS] <INITRD>\n"
328950313ebSMasami Hiramatsu 		" Apply, delete or show boot config to initrd.\n"
329950313ebSMasami Hiramatsu 		" Options:\n"
330950313ebSMasami Hiramatsu 		"		-a <config>: Apply boot config to initrd\n"
331950313ebSMasami Hiramatsu 		"		-d : Delete boot config file from initrd\n\n"
332950313ebSMasami Hiramatsu 		" If no option is given, show current applied boot config.\n");
333950313ebSMasami Hiramatsu 	return -1;
334950313ebSMasami Hiramatsu }
335950313ebSMasami Hiramatsu 
336950313ebSMasami Hiramatsu int main(int argc, char **argv)
337950313ebSMasami Hiramatsu {
338950313ebSMasami Hiramatsu 	char *path = NULL;
339950313ebSMasami Hiramatsu 	char *apply = NULL;
340950313ebSMasami Hiramatsu 	bool delete = false;
341950313ebSMasami Hiramatsu 	int opt;
342950313ebSMasami Hiramatsu 
343950313ebSMasami Hiramatsu 	while ((opt = getopt(argc, argv, "hda:")) != -1) {
344950313ebSMasami Hiramatsu 		switch (opt) {
345950313ebSMasami Hiramatsu 		case 'd':
346950313ebSMasami Hiramatsu 			delete = true;
347950313ebSMasami Hiramatsu 			break;
348950313ebSMasami Hiramatsu 		case 'a':
349950313ebSMasami Hiramatsu 			apply = optarg;
350950313ebSMasami Hiramatsu 			break;
351950313ebSMasami Hiramatsu 		case 'h':
352950313ebSMasami Hiramatsu 		default:
353950313ebSMasami Hiramatsu 			return usage();
354950313ebSMasami Hiramatsu 		}
355950313ebSMasami Hiramatsu 	}
356950313ebSMasami Hiramatsu 
357950313ebSMasami Hiramatsu 	if (apply && delete) {
35897378001SMasami Hiramatsu 		pr_err("Error: You can not specify both -a and -d at once.\n");
359950313ebSMasami Hiramatsu 		return usage();
360950313ebSMasami Hiramatsu 	}
361950313ebSMasami Hiramatsu 
362950313ebSMasami Hiramatsu 	if (optind >= argc) {
36397378001SMasami Hiramatsu 		pr_err("Error: No initrd is specified.\n");
364950313ebSMasami Hiramatsu 		return usage();
365950313ebSMasami Hiramatsu 	}
366950313ebSMasami Hiramatsu 
367950313ebSMasami Hiramatsu 	path = argv[optind];
368950313ebSMasami Hiramatsu 
369950313ebSMasami Hiramatsu 	if (apply)
370950313ebSMasami Hiramatsu 		return apply_xbc(path, apply);
371950313ebSMasami Hiramatsu 	else if (delete)
372950313ebSMasami Hiramatsu 		return delete_xbc(path);
373950313ebSMasami Hiramatsu 
374950313ebSMasami Hiramatsu 	return show_xbc(path);
375950313ebSMasami Hiramatsu }
376