| // 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) |
| { |
| int rc = 0; |
| FILE *fd; |
| size_t i; |
| |
| fd = fopen(pathname, "w"); |
| if (!fd) { |
| rc = errno; |
| goto err; |
| } |
| |
| 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; |
| |
| err: |
| if (fd) |
| fclose(fd); |
| return rc; |
| } |
| |
| 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; |
| } |