1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
4  */
5 
6 #include <stdlib.h>
7 #include <stddef.h>
8 #include <stdio.h>
9 #include <unistd.h>
10 #include <errno.h>
11 
usage(const char * const name)12 static void usage(const char *const name)
13 {
14 	printf("Usage: %s OutputFile (PolicyFile)\n", name);
15 	exit(EINVAL);
16 }
17 
policy_to_buffer(const char * pathname,char ** buffer,size_t * size)18 static int policy_to_buffer(const char *pathname, char **buffer, size_t *size)
19 {
20 	size_t fsize;
21 	size_t read;
22 	char *lbuf;
23 	int rc = 0;
24 	FILE *fd;
25 
26 	fd = fopen(pathname, "r");
27 	if (!fd) {
28 		rc = errno;
29 		goto out;
30 	}
31 
32 	fseek(fd, 0, SEEK_END);
33 	fsize = ftell(fd);
34 	rewind(fd);
35 
36 	lbuf = malloc(fsize);
37 	if (!lbuf) {
38 		rc = ENOMEM;
39 		goto out_close;
40 	}
41 
42 	read = fread((void *)lbuf, sizeof(*lbuf), fsize, fd);
43 	if (read != fsize) {
44 		rc = -1;
45 		goto out_free;
46 	}
47 
48 	*buffer = lbuf;
49 	*size = fsize;
50 	fclose(fd);
51 
52 	return rc;
53 
54 out_free:
55 	free(lbuf);
56 out_close:
57 	fclose(fd);
58 out:
59 	return rc;
60 }
61 
write_boot_policy(const char * pathname,const char * buf,size_t size)62 static int write_boot_policy(const char *pathname, const char *buf, size_t size)
63 {
64 	int rc = 0;
65 	FILE *fd;
66 	size_t i;
67 
68 	fd = fopen(pathname, "w");
69 	if (!fd) {
70 		rc = errno;
71 		goto err;
72 	}
73 
74 	fprintf(fd, "/* This file is automatically generated.");
75 	fprintf(fd, " Do not edit. */\n");
76 	fprintf(fd, "#include <linux/stddef.h>\n");
77 	fprintf(fd, "\nextern const char *const ipe_boot_policy;\n\n");
78 	fprintf(fd, "const char *const ipe_boot_policy =\n");
79 
80 	if (!buf || size == 0) {
81 		fprintf(fd, "\tNULL;\n");
82 		fclose(fd);
83 		return 0;
84 	}
85 
86 	fprintf(fd, "\t\"");
87 
88 	for (i = 0; i < size; ++i) {
89 		switch (buf[i]) {
90 		case '"':
91 			fprintf(fd, "\\\"");
92 			break;
93 		case '\'':
94 			fprintf(fd, "'");
95 			break;
96 		case '\n':
97 			fprintf(fd, "\\n\"\n\t\"");
98 			break;
99 		case '\\':
100 			fprintf(fd, "\\\\");
101 			break;
102 		case '\t':
103 			fprintf(fd, "\\t");
104 			break;
105 		case '\?':
106 			fprintf(fd, "\\?");
107 			break;
108 		default:
109 			fprintf(fd, "%c", buf[i]);
110 		}
111 	}
112 	fprintf(fd, "\";\n");
113 	fclose(fd);
114 
115 	return 0;
116 
117 err:
118 	if (fd)
119 		fclose(fd);
120 	return rc;
121 }
122 
main(int argc,const char * const argv[])123 int main(int argc, const char *const argv[])
124 {
125 	char *policy = NULL;
126 	size_t len = 0;
127 	int rc = 0;
128 
129 	if (argc < 2)
130 		usage(argv[0]);
131 
132 	if (argc > 2) {
133 		rc = policy_to_buffer(argv[2], &policy, &len);
134 		if (rc != 0)
135 			goto cleanup;
136 	}
137 
138 	rc = write_boot_policy(argv[1], policy, len);
139 cleanup:
140 	if (policy)
141 		free(policy);
142 	if (rc != 0)
143 		perror("An error occurred during policy conversion: ");
144 	return rc;
145 }
146