root/scripts/ipe/polgen/polgen.c
// 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;
}