| // SPDX-License-Identifier: GPL-2.0 | |
| /* | |
| * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved. | |
| */ | |
| #include <stdlib.h> | |
| #include <stddef.h> | |
| #include <stdio.h> | |
| #include <unistd.h> | |
| #include <errno.h> | |
| static void usage(const char *const name) | |
| { | |
| printf("Usage: %s OutputFile (PolicyFile)\n", name); | |
| exit(EINVAL); | |
| } | |
| static int policy_to_buffer(const char *pathname, char **buffer, size_t *size) | |
| { | |
| size_t fsize; | |
| size_t read; | |
| char *lbuf; | |
| int rc = 0; | |
| FILE *fd; | |
| fd = fopen(pathname, "r"); | |
| if (!fd) { | |
| rc = errno; | |
| goto out; | |
| } | |
| fseek(fd, 0, SEEK_END); | |
| fsize = ftell(fd); | |
| rewind(fd); | |
| lbuf = malloc(fsize); | |
| if (!lbuf) { | |
| rc = ENOMEM; | |
| goto out_close; | |
| } | |
| read = fread((void *)lbuf, sizeof(*lbuf), fsize, fd); | |
| if (read != fsize) { | |
| rc = -1; | |
| goto out_free; | |
| } | |
| *buffer = lbuf; | |
| *size = fsize; | |
| fclose(fd); | |
| return rc; | |
| out_free: | |
| free(lbuf); | |
| out_close: | |
| fclose(fd); | |
| out: | |
| return rc; | |
| } | |
| static int write_boot_policy(const char *pathname, const char *buf, size_t size) | |
| { | |
| FILE *fd; | |
| size_t i; | |
| fd = fopen(pathname, "w"); | |
| if (!fd) | |
| return errno; | |
| fprintf(fd, "/* This file is automatically generated."); | |
| fprintf(fd, " Do not edit. */\n"); | |
| fprintf(fd, "#include <linux/stddef.h>\n"); | |
| fprintf(fd, "\nextern const char *const ipe_boot_policy;\n\n"); | |
| fprintf(fd, "const char *const ipe_boot_policy =\n"); | |
| if (!buf || size == 0) { | |
| fprintf(fd, "\tNULL;\n"); | |
| fclose(fd); | |
| return 0; | |
| } | |
| fprintf(fd, "\t\""); | |
| for (i = 0; i < size; ++i) { | |
| switch (buf[i]) { | |
| case '"': | |
| fprintf(fd, "\\\""); | |
| break; | |
| case '\'': | |
| fprintf(fd, "'"); | |
| break; | |
| case '\n': | |
| fprintf(fd, "\\n\"\n\t\""); | |
| break; | |
| case '\\': | |
| fprintf(fd, "\\\\"); | |
| break; | |
| case '\t': | |
| fprintf(fd, "\\t"); | |
| break; | |
| case '\?': | |
| fprintf(fd, "\\?"); | |
| break; | |
| default: | |
| fprintf(fd, "%c", buf[i]); | |
| } | |
| } | |
| fprintf(fd, "\";\n"); | |
| fclose(fd); | |
| return 0; | |
| } | |
| int main(int argc, const char *const argv[]) | |
| { | |
| char *policy = NULL; | |
| size_t len = 0; | |
| int rc = 0; | |
| if (argc < 2) | |
| usage(argv[0]); | |
| if (argc > 2) { | |
| rc = policy_to_buffer(argv[2], &policy, &len); | |
| if (rc != 0) | |
| goto cleanup; | |
| } | |
| rc = write_boot_policy(argv[1], policy, len); | |
| cleanup: | |
| if (policy) | |
| free(policy); | |
| if (rc != 0) | |
| perror("An error occurred during policy conversion: "); | |
| return rc; | |
| } |