amduat/src/tools/amduat_pel_cli.c

2553 lines
86 KiB
C
Raw Normal View History

#include "amduat/asl/artifact_io.h"
#include "amduat/asl/asl_store_fs.h"
#include "amduat/asl/asl_store_fs_meta.h"
#include "amduat/asl/io.h"
#include "amduat/asl/parse.h"
#include "amduat/asl/ref_io.h"
#include "amduat/asl/ref_text.h"
#include "amduat/asl/store.h"
#include "amduat/enc/asl1_core_codec.h"
#include "amduat/enc/pel1_result.h"
#include "amduat/enc/pel_program_dag.h"
#include "amduat/enc/pel_trace_dag.h"
#include "amduat/format/json.h"
#include "amduat/format/opreg_util.h"
#include "amduat/format/output.h"
#include "amduat/format/parse.h"
#include "amduat/format/pel.h"
#include "amduat/format/ref.h"
#include "amduat/pel/decode.h"
#include "amduat/pel/opreg_kernel.h"
#include "amduat/pel/opreg_kernel_params.h"
#include "amduat/pel/program_dag_desc.h"
#include "amduat/pel/run.h"
#include "amduat/pel/surf.h"
#include <ctype.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum {
AMDUAT_PEL_CLI_EXIT_OK = 0,
AMDUAT_PEL_CLI_EXIT_USAGE = 2,
AMDUAT_PEL_CLI_EXIT_IO = 3,
AMDUAT_PEL_CLI_EXIT_NOT_FOUND = 4,
AMDUAT_PEL_CLI_EXIT_STORE = 5,
AMDUAT_PEL_CLI_EXIT_UNSUPPORTED = 6,
AMDUAT_PEL_CLI_EXIT_CODEC = 7,
AMDUAT_PEL_CLI_EXIT_CONFIG = 8
};
static const char *const AMDUAT_PEL_CLI_DEFAULT_ROOT = ".amduat-asl";
typedef struct {
const char *root;
amduat_format_ref_format_t ref_format;
amduat_format_output_t format;
bool quiet;
} amduat_pel_cli_global_opts_t;
static void amduat_pel_cli_print_usage(FILE *stream) {
fprintf(stream,
"usage:\n"
" amduat-pel [--root PATH] [--ref-format hex|bytes] [--format text|json]\n"
" [--quiet] <command> [args]\n"
"\n"
"commands:\n"
" run Execute a PEL/PROGRAM-DAG/1 program via PEL/1-SURF (store-backed).\n"
" exec Execute a PEL/PROGRAM-DAG/1 program in-memory (no store writes).\n"
" validate Validate a Program artifact (decode + DAG checks + params).\n"
" program Program DAG tools (decode, normalize).\n"
" trace Trace DAG tools (decode, from-result).\n"
" result Surface result tools (decode).\n"
" op Kernel op registry tools.\n"
" scheme Scheme refs, type tags, profile IDs.\n"
" help Show help for a command.\n"
"\n"
"global options:\n"
" --root PATH ASL store root (default .amduat-asl)\n"
" --ref-format hex|bytes Reference I/O format (default hex)\n"
" --format text|json Structured output format (default text)\n"
" --quiet Only print machine output\n"
"\n"
"run:\n"
" amduat-pel run --program-ref REF [--scheme-ref REF|dag]\n"
" [--input-ref REF ...] [--inputs-file PATH]\n"
" [--params-ref REF]\n"
" [--format text|json] [--ref-format hex|bytes]\n"
" Output: result_ref, trace_ref, output_refs (formatted per --format).\n"
"\n"
"exec:\n"
" amduat-pel exec --program PATH|-\n"
" [--input PATH ...] [--input-format raw|artifact]\n"
" [--output-dir DIR] [--output-format raw|artifact]\n"
" [--result-out PATH|-] [--format text|json]\n"
"\n"
"validate:\n"
" amduat-pel validate [--input PATH|- | --program-ref REF]\n"
" [--input-format raw|artifact]\n"
" [--expect-type-tag TAG]\n"
" [--format text|json]\n"
"\n"
"program:\n"
" amduat-pel program decode [--input PATH|- | --program-ref REF]\n"
" [--input-format raw|artifact]\n"
" [--expect-type-tag TAG]\n"
" [--format text|json]\n"
" amduat-pel program normalize --input PATH|- [--input-format raw|artifact]\n"
" [--output PATH|-] [--output-format raw|artifact]\n"
" [--type-tag TAG]\n"
"\n"
"trace:\n"
" amduat-pel trace decode [--input PATH|- | --trace-ref REF]\n"
" [--input-format raw|artifact]\n"
" [--expect-type-tag TAG]\n"
" [--format text|json]\n"
" amduat-pel trace from-result --result-ref REF [--root PATH]\n"
" [--format text|json]\n"
"\n"
"result:\n"
" amduat-pel result decode [--input PATH|- | --result-ref REF]\n"
" [--input-format raw|artifact]\n"
" [--expect-type-tag TAG]\n"
" [--format text|json]\n"
"\n"
"op:\n"
" amduat-pel op list [--format text|json]\n"
" amduat-pel op describe NAME[=VERSION] [--format text|json]\n"
" amduat-pel op params-decode --op NAME[=VERSION]\n"
" --input PATH|- [--format text|json]\n"
"\n"
"scheme:\n"
" amduat-pel scheme show [--format text|json]\n"
" amduat-pel scheme dag-ref [--format hex|bytes]\n"
"\n"
"defaults:\n"
" --root .amduat-asl\n"
" --ref-format hex\n"
" --input -\n"
" --output -\n"
" --input-format raw\n"
" --output-format raw\n"
" --scheme-ref dag\n"
"\n"
"notes:\n"
" - Only PEL/PROGRAM-DAG/1 is supported; other scheme refs yield SCHEME_UNSUPPORTED.\n"
" - Expected type tags: program 0x00000101, trace 0x00000102, result 0x00000103.\n"
" - Encoding profile IDs: program 0x0101, trace 0x0102, result 0x0103.\n"
" - Kernel ops: pel.bytes.concat, pel.bytes.slice, pel.bytes.const, pel.bytes.hash.asl1.\n"
" - --ref-format bytes expects REF arguments to be a path or '-' (raw reference bytes).\n"
" - --inputs-file with --ref-format bytes expects raw concatenated references.\n");
}
static const char *amduat_pel_cli_store_error_str(
amduat_asl_store_error_t err) {
switch (err) {
case AMDUAT_ASL_STORE_ERR_NOT_FOUND:
return "not found";
case AMDUAT_ASL_STORE_ERR_UNSUPPORTED:
return "unsupported";
case AMDUAT_ASL_STORE_ERR_INTEGRITY:
return "integrity";
case AMDUAT_ASL_STORE_OK:
return "ok";
default:
return "unknown";
}
}
static int amduat_pel_cli_map_store_error(amduat_asl_store_error_t err) {
switch (err) {
case AMDUAT_ASL_STORE_ERR_NOT_FOUND:
return AMDUAT_PEL_CLI_EXIT_NOT_FOUND;
case AMDUAT_ASL_STORE_ERR_UNSUPPORTED:
return AMDUAT_PEL_CLI_EXIT_UNSUPPORTED;
case AMDUAT_ASL_STORE_ERR_INTEGRITY:
return AMDUAT_PEL_CLI_EXIT_STORE;
case AMDUAT_ASL_STORE_OK:
default:
return AMDUAT_PEL_CLI_EXIT_STORE;
}
}
static void amduat_pel_cli_free_reference(amduat_reference_t *ref) {
if (ref == NULL) {
return;
}
free((void *)ref->digest.data);
ref->digest.data = NULL;
ref->digest.len = 0u;
}
static void amduat_pel_cli_free_refs(amduat_reference_t *refs, size_t refs_len) {
size_t i;
if (refs == NULL) {
return;
}
for (i = 0; i < refs_len; ++i) {
amduat_pel_cli_free_reference(&refs[i]);
}
free(refs);
}
static bool amduat_pel_cli_read_path_once(const char *path,
bool *stdin_used,
uint8_t **out_bytes,
size_t *out_len) {
if (path == NULL || out_bytes == NULL || out_len == NULL) {
return false;
}
if (strcmp(path, "-") == 0 && stdin_used != NULL) {
if (*stdin_used) {
return false;
}
*stdin_used = true;
}
return amduat_asl_read_path(path, out_bytes, out_len);
}
static bool amduat_pel_cli_ref_from_text(const char *text,
amduat_format_ref_format_t fmt,
bool *stdin_used,
amduat_reference_t *out_ref) {
bool ok;
if (text == NULL || out_ref == NULL) {
return false;
}
memset(out_ref, 0, sizeof(*out_ref));
if (fmt == AMDUAT_FORMAT_REF_HEX) {
return amduat_asl_ref_decode_format(
fmt, amduat_octets(text, strlen(text)), out_ref);
}
{
uint8_t *bytes = NULL;
size_t len = 0;
if (!amduat_pel_cli_read_path_once(text, stdin_used, &bytes, &len)) {
return false;
}
ok = amduat_asl_ref_decode_format(fmt, amduat_octets(bytes, len), out_ref);
free(bytes);
return ok;
}
}
static bool amduat_pel_cli_append_ref(amduat_reference_t **refs,
size_t *refs_len,
amduat_reference_t ref) {
amduat_reference_t *next;
if (refs == NULL || refs_len == NULL) {
return false;
}
next = (amduat_reference_t *)realloc(
*refs, (*refs_len + 1u) * sizeof(**refs));
if (next == NULL) {
return false;
}
next[*refs_len] = ref;
*refs = next;
*refs_len += 1u;
return true;
}
static bool amduat_pel_cli_append_refs_from_file(
const char *path,
amduat_format_ref_format_t fmt,
bool *stdin_used,
amduat_reference_t **refs,
size_t *refs_len) {
uint8_t *bytes = NULL;
size_t len = 0;
amduat_reference_t *parsed = NULL;
size_t parsed_len = 0;
amduat_reference_t *next;
if (!amduat_pel_cli_read_path_once(path, stdin_used, &bytes, &len)) {
return false;
}
if (!amduat_asl_ref_list_parse(amduat_octets(bytes, len),
fmt,
&parsed,
&parsed_len)) {
free(bytes);
return false;
}
free(bytes);
if (parsed_len == 0) {
free(parsed);
return true;
}
if (*refs == NULL) {
*refs = parsed;
*refs_len = parsed_len;
return true;
}
next = (amduat_reference_t *)realloc(
*refs, (*refs_len + parsed_len) * sizeof(**refs));
if (next == NULL) {
amduat_asl_ref_list_free(parsed, parsed_len);
return false;
}
memcpy(next + *refs_len, parsed, parsed_len * sizeof(*parsed));
free(parsed);
*refs = next;
*refs_len += parsed_len;
return true;
}
static int amduat_pel_cli_cmd_run(int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
const char *program_ref_text = NULL;
const char *scheme_ref_text = "dag";
const char *params_ref_text = NULL;
const char *inputs_file = NULL;
const char **input_ref_texts = NULL;
size_t input_ref_texts_len = 0;
amduat_format_ref_format_t ref_format;
amduat_format_output_t format;
const char *root;
bool quiet;
bool has_params_ref = false;
amduat_reference_t program_ref;
amduat_reference_t scheme_ref;
amduat_reference_t params_ref;
amduat_reference_t *input_refs = NULL;
size_t input_refs_len = 0;
amduat_pel_run_result_t run_result;
amduat_reference_t trace_ref;
bool has_trace_ref = false;
amduat_asl_store_fs_config_t cfg;
amduat_asl_store_fs_t fs;
amduat_asl_store_t store;
bool stdin_used = false;
int exit_code = AMDUAT_PEL_CLI_EXIT_OK;
int i;
if (global == NULL) {
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
root = global->root;
ref_format = global->ref_format;
format = global->format;
quiet = global->quiet;
for (i = 0; i < argc; ++i) {
if (strcmp(argv[i], "--program-ref") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --program-ref requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
program_ref_text = argv[++i];
} else if (strcmp(argv[i], "--scheme-ref") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --scheme-ref requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
scheme_ref_text = argv[++i];
} else if (strcmp(argv[i], "--input-ref") == 0) {
const char **next;
if (i + 1 >= argc) {
fprintf(stderr, "error: --input-ref requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
next = (const char **)realloc(
input_ref_texts,
(input_ref_texts_len + 1u) * sizeof(*input_ref_texts));
if (next == NULL) {
fprintf(stderr, "error: out of memory\n");
return AMDUAT_PEL_CLI_EXIT_STORE;
}
input_ref_texts = next;
input_ref_texts[input_ref_texts_len++] = argv[++i];
} else if (strcmp(argv[i], "--inputs-file") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --inputs-file requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
inputs_file = argv[++i];
} else if (strcmp(argv[i], "--params-ref") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --params-ref requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
params_ref_text = argv[++i];
has_params_ref = true;
} else if (strcmp(argv[i], "--format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_output_parse(argv[++i], &format)) {
fprintf(stderr, "error: invalid format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--ref-format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --ref-format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_ref_parse(argv[++i], &ref_format)) {
fprintf(stderr, "error: invalid ref-format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--root") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --root requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
root = argv[++i];
} else if (strcmp(argv[i], "--quiet") == 0) {
quiet = true;
} else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
amduat_pel_cli_print_usage(stdout);
return AMDUAT_PEL_CLI_EXIT_OK;
} else {
fprintf(stderr, "error: unknown option: %s\n", argv[i]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
}
if (program_ref_text == NULL) {
fprintf(stderr, "error: --program-ref is required\n");
free(input_ref_texts);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_asl_store_fs_load_config(root, &cfg)) {
fprintf(stderr, "error: failed to load store config: %s\n", root);
free(input_ref_texts);
return AMDUAT_PEL_CLI_EXIT_CONFIG;
}
if (!amduat_asl_store_fs_init(&fs, cfg.config, root)) {
fprintf(stderr, "error: failed to initialize store\n");
free(input_ref_texts);
return AMDUAT_PEL_CLI_EXIT_CONFIG;
}
amduat_asl_store_init(&store, cfg.config, amduat_asl_store_fs_ops(), &fs);
if (!amduat_pel_cli_ref_from_text(program_ref_text,
ref_format,
&stdin_used,
&program_ref)) {
fprintf(stderr, "error: invalid --program-ref\n");
free(input_ref_texts);
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
if (strcmp(scheme_ref_text, "dag") == 0) {
scheme_ref = amduat_pel_program_dag_scheme_ref();
} else if (!amduat_pel_cli_ref_from_text(scheme_ref_text,
ref_format,
&stdin_used,
&scheme_ref)) {
amduat_pel_cli_free_reference(&program_ref);
free(input_ref_texts);
fprintf(stderr, "error: invalid --scheme-ref\n");
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
if (has_params_ref) {
if (!amduat_pel_cli_ref_from_text(params_ref_text,
ref_format,
&stdin_used,
&params_ref)) {
amduat_pel_cli_free_reference(&program_ref);
if (strcmp(scheme_ref_text, "dag") != 0) {
amduat_pel_cli_free_reference(&scheme_ref);
}
free(input_ref_texts);
fprintf(stderr, "error: invalid --params-ref\n");
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
} else {
memset(&params_ref, 0, sizeof(params_ref));
}
for (i = 0; i < (int)input_ref_texts_len; ++i) {
amduat_reference_t ref;
if (!amduat_pel_cli_ref_from_text(input_ref_texts[i],
ref_format,
&stdin_used,
&ref)) {
fprintf(stderr, "error: invalid --input-ref\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
goto run_cleanup;
}
if (!amduat_pel_cli_append_ref(&input_refs, &input_refs_len, ref)) {
amduat_pel_cli_free_reference(&ref);
fprintf(stderr, "error: out of memory\n");
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
goto run_cleanup;
}
}
if (inputs_file != NULL) {
if (!amduat_pel_cli_append_refs_from_file(inputs_file,
ref_format,
&stdin_used,
&input_refs,
&input_refs_len)) {
fprintf(stderr, "error: failed to read inputs file\n");
exit_code = AMDUAT_PEL_CLI_EXIT_IO;
goto run_cleanup;
}
}
memset(&run_result, 0, sizeof(run_result));
if (!amduat_pel_surf_run_with_result(&store,
scheme_ref,
program_ref,
input_refs,
input_refs_len,
has_params_ref,
params_ref,
&run_result)) {
fprintf(stderr, "error: PEL surface execution failed\n");
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
goto run_cleanup;
}
memset(&trace_ref, 0, sizeof(trace_ref));
if (run_result.has_result_value && run_result.result_value.has_trace_ref) {
trace_ref = run_result.result_value.trace_ref;
has_trace_ref = true;
}
if (!quiet) {
fprintf(stderr, "root=%s\n", root);
fprintf(stderr, "program_ref=");
if (!amduat_format_ref_write_text(stderr, program_ref, ref_format)) {
fprintf(stderr, "\n");
} else {
fputc('\n', stderr);
}
if (has_params_ref) {
fprintf(stderr, "params_ref=");
if (!amduat_format_ref_write_text(stderr, params_ref, ref_format)) {
fprintf(stderr, "\n");
} else {
fputc('\n', stderr);
}
}
if (run_result.has_result_value) {
fprintf(stderr, "status=%s(%u)\n",
amduat_format_pel_status_name(
run_result.result_value.core_result.status),
(unsigned int)run_result.result_value.core_result.status);
fprintf(stderr, "error_kind=%s(%u)\n",
amduat_format_pel_error_kind_name(
run_result.result_value.core_result.summary.kind),
(unsigned int)run_result.result_value.core_result.summary.kind);
fprintf(stderr, "status_code=%u\n",
(unsigned int)run_result.result_value.core_result.summary.status_code);
}
}
if (format == AMDUAT_FORMAT_OUTPUT_TEXT) {
fprintf(stdout, "result_ref=");
if (!amduat_format_ref_write_text(stdout,
run_result.result_ref,
ref_format)) {
fprintf(stderr, "error: failed to encode result ref\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
goto run_cleanup;
}
fputc('\n', stdout);
if (has_trace_ref) {
fprintf(stdout, "trace_ref=");
if (!amduat_format_ref_write_text(stdout, trace_ref, ref_format)) {
fprintf(stderr, "error: failed to encode trace ref\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
goto run_cleanup;
}
fputc('\n', stdout);
}
for (i = 0; i < (int)run_result.output_refs_len; ++i) {
fprintf(stdout, "output_ref[%d]=", i);
if (!amduat_format_ref_write_text(stdout,
run_result.output_refs[i],
ref_format)) {
fprintf(stderr, "error: failed to encode output ref\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
goto run_cleanup;
}
fputc('\n', stdout);
}
} else {
fputs("{\"ref_format\":\"", stdout);
fputs(ref_format == AMDUAT_FORMAT_REF_HEX ? "hex" : "bytes", stdout);
fputs("\",\"result_ref\":", stdout);
if (!amduat_format_ref_write_json(stdout,
run_result.result_ref,
ref_format)) {
fprintf(stderr, "error: failed to encode result ref\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
goto run_cleanup;
}
fputs(",\"trace_ref\":", stdout);
if (has_trace_ref) {
if (!amduat_format_ref_write_json(stdout, trace_ref, ref_format)) {
fprintf(stderr, "error: failed to encode trace ref\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
goto run_cleanup;
}
} else {
fputs("null", stdout);
}
fputs(",\"output_refs\":[", stdout);
for (i = 0; i < (int)run_result.output_refs_len; ++i) {
if (i != 0) {
fputc(',', stdout);
}
if (!amduat_format_ref_write_json(stdout,
run_result.output_refs[i],
ref_format)) {
fprintf(stderr, "error: failed to encode output ref\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
goto run_cleanup;
}
}
fputs("]}\n", stdout);
}
run_cleanup:
if (run_result.has_result_value) {
amduat_enc_pel1_result_free(&run_result.result_value);
}
if (run_result.output_refs != NULL) {
amduat_pel_surf_free_refs(run_result.output_refs,
run_result.output_refs_len);
}
amduat_pel_surf_free_ref(&run_result.result_ref);
if (input_refs != NULL) {
amduat_pel_cli_free_refs(input_refs, input_refs_len);
}
if (has_params_ref) {
amduat_pel_cli_free_reference(&params_ref);
}
amduat_pel_cli_free_reference(&program_ref);
if (strcmp(scheme_ref_text, "dag") != 0) {
amduat_pel_cli_free_reference(&scheme_ref);
}
free(input_ref_texts);
return exit_code;
}
static int amduat_pel_cli_cmd_exec(int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
const char *program_path = NULL;
const char **input_paths = NULL;
size_t input_paths_len = 0;
amduat_asl_io_format_t input_format = AMDUAT_ASL_IO_RAW;
amduat_asl_io_format_t output_format = AMDUAT_ASL_IO_RAW;
amduat_format_output_t format;
const char *output_dir = ".";
const char *result_out = "-";
amduat_artifact_t *inputs = NULL;
amduat_artifact_t *outputs = NULL;
size_t outputs_len = 0;
amduat_pel_execution_result_value_t result;
uint8_t *program_bytes = NULL;
size_t program_len = 0;
bool stdin_used = false;
int exit_code = AMDUAT_PEL_CLI_EXIT_OK;
FILE *out_stream = NULL;
int i;
if (global == NULL) {
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
format = global->format;
for (i = 0; i < argc; ++i) {
if (strcmp(argv[i], "--program") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --program requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
program_path = argv[++i];
} else if (strcmp(argv[i], "--input") == 0) {
const char **next;
if (i + 1 >= argc) {
fprintf(stderr, "error: --input requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
next = (const char **)realloc(
input_paths, (input_paths_len + 1u) * sizeof(*input_paths));
if (next == NULL) {
fprintf(stderr, "error: out of memory\n");
return AMDUAT_PEL_CLI_EXIT_STORE;
}
input_paths = next;
input_paths[input_paths_len++] = argv[++i];
} else if (strcmp(argv[i], "--input-format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --input-format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_asl_io_format_parse(argv[++i], &input_format)) {
fprintf(stderr, "error: invalid input-format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--output-dir") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --output-dir requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
output_dir = argv[++i];
} else if (strcmp(argv[i], "--output-format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --output-format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_asl_io_format_parse(argv[++i], &output_format)) {
fprintf(stderr, "error: invalid output-format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--result-out") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --result-out requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
result_out = argv[++i];
} else if (strcmp(argv[i], "--format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_output_parse(argv[++i], &format)) {
fprintf(stderr, "error: invalid format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
amduat_pel_cli_print_usage(stdout);
free(input_paths);
return AMDUAT_PEL_CLI_EXIT_OK;
} else {
fprintf(stderr, "error: unknown option: %s\n", argv[i]);
free(input_paths);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
}
if (program_path == NULL) {
fprintf(stderr, "error: --program is required\n");
free(input_paths);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_pel_cli_read_path_once(program_path,
&stdin_used,
&program_bytes,
&program_len)) {
fprintf(stderr, "error: failed to read program\n");
free(input_paths);
return AMDUAT_PEL_CLI_EXIT_IO;
}
if (input_paths_len > 0) {
inputs = (amduat_artifact_t *)calloc(
input_paths_len, sizeof(*inputs));
if (inputs == NULL) {
fprintf(stderr, "error: out of memory\n");
free(program_bytes);
free(input_paths);
return AMDUAT_PEL_CLI_EXIT_STORE;
}
}
for (i = 0; i < (int)input_paths_len; ++i) {
uint8_t *bytes = NULL;
size_t len = 0;
if (!amduat_pel_cli_read_path_once(input_paths[i],
&stdin_used,
&bytes,
&len)) {
fprintf(stderr, "error: failed to read input: %s\n", input_paths[i]);
free(program_bytes);
program_bytes = NULL;
exit_code = AMDUAT_PEL_CLI_EXIT_IO;
goto exec_cleanup;
}
if (!amduat_asl_artifact_from_bytes(amduat_octets(bytes, len),
input_format,
false,
amduat_type_tag(0),
&inputs[i])) {
free(bytes);
fprintf(stderr, "error: invalid input artifact\n");
free(program_bytes);
program_bytes = NULL;
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
goto exec_cleanup;
}
if (input_format == AMDUAT_ASL_IO_ARTIFACT) {
free(bytes);
} else {
/* raw inputs borrow bytes; freed via artifact cleanup */
}
}
if (!amduat_pel_exec_program_bytes(amduat_octets(program_bytes,
program_len),
inputs,
input_paths_len,
&outputs,
&outputs_len,
&result)) {
fprintf(stderr, "error: exec failed\n");
free(program_bytes);
program_bytes = NULL;
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
goto exec_cleanup;
}
free(program_bytes);
program_bytes = NULL;
for (i = 0; i < (int)outputs_len; ++i) {
char path_buf[4096];
if (snprintf(path_buf, sizeof(path_buf), "%s/output-%d",
output_dir, i) < 0) {
fprintf(stderr, "error: failed to build output path\n");
exit_code = AMDUAT_PEL_CLI_EXIT_IO;
goto exec_cleanup;
}
if (output_format == AMDUAT_ASL_IO_RAW) {
if (!amduat_asl_write_path(path_buf,
outputs[i].bytes.data,
outputs[i].bytes.len)) {
fprintf(stderr, "error: failed to write output: %s\n", path_buf);
exit_code = AMDUAT_PEL_CLI_EXIT_IO;
goto exec_cleanup;
}
} else {
amduat_octets_t encoded;
if (!amduat_enc_asl1_core_encode_artifact_v1(outputs[i], &encoded)) {
fprintf(stderr, "error: failed to encode output artifact\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
goto exec_cleanup;
}
if (!amduat_asl_write_path(path_buf, encoded.data, encoded.len)) {
fprintf(stderr, "error: failed to write output: %s\n", path_buf);
free((void *)encoded.data);
exit_code = AMDUAT_PEL_CLI_EXIT_IO;
goto exec_cleanup;
}
free((void *)encoded.data);
}
}
if (strcmp(result_out, "-") == 0) {
out_stream = stdout;
} else {
out_stream = fopen(result_out, "wb");
if (out_stream == NULL) {
fprintf(stderr, "error: failed to open result-out: %s\n", result_out);
exit_code = AMDUAT_PEL_CLI_EXIT_IO;
goto exec_cleanup;
}
}
if (format == AMDUAT_FORMAT_OUTPUT_TEXT) {
fprintf(out_stream, "status=%s(%u)\n",
amduat_format_pel_status_name(result.status),
(unsigned int)result.status);
fprintf(out_stream, "error_kind=%s(%u)\n",
amduat_format_pel_error_kind_name(result.summary.kind),
(unsigned int)result.summary.kind);
fprintf(out_stream, "status_code=%u\n",
(unsigned int)result.summary.status_code);
fprintf(out_stream, "outputs_len=%zu\n", outputs_len);
for (i = 0; i < (int)outputs_len; ++i) {
fprintf(out_stream, "output_path[%d]=%s/output-%d\n",
i, output_dir, i);
}
} else {
fputs("{\"status\":", out_stream);
amduat_format_json_escape(
out_stream,
amduat_octets(amduat_format_pel_status_name(result.status),
strlen(amduat_format_pel_status_name(result.status))));
fprintf(out_stream, ",\"status_code\":%u",
(unsigned int)result.summary.status_code);
fputs(",\"error_kind\":", out_stream);
amduat_format_json_escape(
out_stream,
amduat_octets(amduat_format_pel_error_kind_name(result.summary.kind),
strlen(amduat_format_pel_error_kind_name(
result.summary.kind))));
fprintf(out_stream, ",\"error_kind_code\":%u",
(unsigned int)result.summary.kind);
fputs(",\"output_paths\":[", out_stream);
for (i = 0; i < (int)outputs_len; ++i) {
if (i != 0) {
fputc(',', out_stream);
}
{
char path_buf[4096];
if (snprintf(path_buf, sizeof(path_buf), "%s/output-%d",
output_dir, i) < 0) {
fprintf(stderr, "error: failed to build output path\n");
exit_code = AMDUAT_PEL_CLI_EXIT_IO;
goto exec_cleanup;
}
amduat_format_json_escape(
out_stream, amduat_octets(path_buf, strlen(path_buf)));
}
}
fputs("]}\n", out_stream);
}
exec_cleanup:
if (out_stream != NULL && out_stream != stdout) {
fclose(out_stream);
}
if (outputs != NULL) {
amduat_pel_program_dag_free_outputs(outputs, outputs_len);
}
if (inputs != NULL) {
for (i = 0; i < (int)input_paths_len; ++i) {
amduat_asl_artifact_free(&inputs[i]);
}
free(inputs);
}
if (program_bytes != NULL) {
free(program_bytes);
}
free(input_paths);
return exit_code;
}
static int amduat_pel_cli_cmd_validate(
int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
const char *input_path = "-";
const char *program_ref_text = NULL;
bool input_path_set = false;
amduat_asl_io_format_t input_format = AMDUAT_ASL_IO_RAW;
amduat_format_output_t format;
amduat_format_ref_format_t ref_format;
const char *root;
bool has_expect_type_tag = false;
amduat_type_tag_t expect_type_tag;
amduat_asl_store_fs_config_t cfg;
amduat_asl_store_fs_t fs;
amduat_asl_store_t store;
amduat_reference_t program_ref;
amduat_artifact_t artifact;
bool stdin_used = false;
bool valid = false;
int exit_code = AMDUAT_PEL_CLI_EXIT_OK;
int i;
if (global == NULL) {
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
format = global->format;
ref_format = global->ref_format;
root = global->root;
for (i = 0; i < argc; ++i) {
if (strcmp(argv[i], "--input") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --input requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
input_path = argv[++i];
input_path_set = true;
} else if (strcmp(argv[i], "--program-ref") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --program-ref requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
program_ref_text = argv[++i];
} else if (strcmp(argv[i], "--input-format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --input-format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_asl_io_format_parse(argv[++i], &input_format)) {
fprintf(stderr, "error: invalid input-format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--expect-type-tag") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --expect-type-tag requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_asl_parse_type_tag(argv[++i], &expect_type_tag)) {
fprintf(stderr, "error: invalid expect-type-tag\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
has_expect_type_tag = true;
} else if (strcmp(argv[i], "--format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_output_parse(argv[++i], &format)) {
fprintf(stderr, "error: invalid format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--ref-format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --ref-format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_ref_parse(argv[++i], &ref_format)) {
fprintf(stderr, "error: invalid ref-format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--root") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --root requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
root = argv[++i];
} else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
amduat_pel_cli_print_usage(stdout);
return AMDUAT_PEL_CLI_EXIT_OK;
} else {
fprintf(stderr, "error: unknown option: %s\n", argv[i]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
}
if (program_ref_text != NULL && input_path_set) {
fprintf(stderr, "error: use --input or --program-ref\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
memset(&artifact, 0, sizeof(artifact));
if (program_ref_text != NULL) {
if (!amduat_asl_store_fs_load_config(root, &cfg)) {
fprintf(stderr, "error: failed to load store config: %s\n", root);
return AMDUAT_PEL_CLI_EXIT_CONFIG;
}
if (!amduat_asl_store_fs_init(&fs, cfg.config, root)) {
fprintf(stderr, "error: failed to initialize store\n");
return AMDUAT_PEL_CLI_EXIT_CONFIG;
}
amduat_asl_store_init(&store, cfg.config, amduat_asl_store_fs_ops(), &fs);
if (!amduat_pel_cli_ref_from_text(program_ref_text,
ref_format,
&stdin_used,
&program_ref)) {
fprintf(stderr, "error: invalid program-ref\n");
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
{
amduat_asl_store_error_t err =
amduat_asl_store_get(&store, program_ref, &artifact);
if (err != AMDUAT_ASL_STORE_OK) {
fprintf(stderr, "error: store get failed: %s\n",
amduat_pel_cli_store_error_str(err));
amduat_pel_cli_free_reference(&program_ref);
return amduat_pel_cli_map_store_error(err);
}
}
amduat_pel_cli_free_reference(&program_ref);
} else {
uint8_t *bytes = NULL;
size_t len = 0;
if (!amduat_pel_cli_read_path_once(input_path,
&stdin_used,
&bytes,
&len)) {
fprintf(stderr, "error: failed to read input\n");
return AMDUAT_PEL_CLI_EXIT_IO;
}
if (!amduat_asl_artifact_from_bytes(amduat_octets(bytes, len),
input_format,
false,
amduat_type_tag(0),
&artifact)) {
free(bytes);
fprintf(stderr, "error: invalid artifact encoding\n");
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
if (input_format == AMDUAT_ASL_IO_ARTIFACT) {
free(bytes);
}
}
if (has_expect_type_tag) {
if (!amduat_asl_artifact_expect_type_tag(&artifact, expect_type_tag)) {
fprintf(stderr, "error: type-tag mismatch\n");
amduat_asl_artifact_free(&artifact);
return AMDUAT_PEL_CLI_EXIT_UNSUPPORTED;
}
}
if (artifact.has_type_tag &&
artifact.type_tag.tag_id != AMDUAT_PEL_TYPE_TAG_PROGRAM_DAG_1) {
fprintf(stderr, "error: type-tag mismatch\n");
amduat_asl_artifact_free(&artifact);
return AMDUAT_PEL_CLI_EXIT_UNSUPPORTED;
}
if (!amduat_pel_program_validate_artifact(&artifact, &valid)) {
fprintf(stderr, "error: invalid program encoding\n");
amduat_asl_artifact_free(&artifact);
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
amduat_asl_artifact_free(&artifact);
if (format == AMDUAT_FORMAT_OUTPUT_TEXT) {
fprintf(stdout, "valid=%s\n", valid ? "true" : "false");
} else {
fprintf(stdout, "{\"valid\":%s}\n", valid ? "true" : "false");
}
if (!valid) {
exit_code = AMDUAT_PEL_CLI_EXIT_UNSUPPORTED;
}
return exit_code;
}
static int amduat_pel_cli_cmd_program_decode(
int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
const char *input_path = "-";
const char *program_ref_text = NULL;
bool input_path_set = false;
amduat_asl_io_format_t input_format = AMDUAT_ASL_IO_RAW;
amduat_format_output_t format;
amduat_format_ref_format_t ref_format;
const char *root;
bool has_expect_type_tag = false;
amduat_type_tag_t expect_type_tag;
amduat_asl_store_fs_config_t cfg;
amduat_asl_store_fs_t fs;
amduat_asl_store_t store;
amduat_reference_t program_ref;
amduat_artifact_t artifact;
amduat_pel_program_t program;
bool stdin_used = false;
int exit_code = AMDUAT_PEL_CLI_EXIT_OK;
int i;
if (global == NULL) {
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
format = global->format;
ref_format = global->ref_format;
root = global->root;
for (i = 0; i < argc; ++i) {
if (strcmp(argv[i], "--input") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --input requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
input_path = argv[++i];
input_path_set = true;
} else if (strcmp(argv[i], "--program-ref") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --program-ref requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
program_ref_text = argv[++i];
} else if (strcmp(argv[i], "--input-format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --input-format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_asl_io_format_parse(argv[++i], &input_format)) {
fprintf(stderr, "error: invalid input-format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--expect-type-tag") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --expect-type-tag requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_asl_parse_type_tag(argv[++i], &expect_type_tag)) {
fprintf(stderr, "error: invalid expect-type-tag\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
has_expect_type_tag = true;
} else if (strcmp(argv[i], "--format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_output_parse(argv[++i], &format)) {
fprintf(stderr, "error: invalid format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--ref-format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --ref-format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_ref_parse(argv[++i], &ref_format)) {
fprintf(stderr, "error: invalid ref-format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--root") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --root requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
root = argv[++i];
} else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
amduat_pel_cli_print_usage(stdout);
return AMDUAT_PEL_CLI_EXIT_OK;
} else {
fprintf(stderr, "error: unknown option: %s\n", argv[i]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
}
if (program_ref_text != NULL && input_path_set) {
fprintf(stderr, "error: use --input or --program-ref\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
memset(&artifact, 0, sizeof(artifact));
if (program_ref_text != NULL) {
if (!amduat_asl_store_fs_load_config(root, &cfg)) {
fprintf(stderr, "error: failed to load store config: %s\n", root);
return AMDUAT_PEL_CLI_EXIT_CONFIG;
}
if (!amduat_asl_store_fs_init(&fs, cfg.config, root)) {
fprintf(stderr, "error: failed to initialize store\n");
return AMDUAT_PEL_CLI_EXIT_CONFIG;
}
amduat_asl_store_init(&store, cfg.config, amduat_asl_store_fs_ops(), &fs);
if (!amduat_pel_cli_ref_from_text(program_ref_text,
ref_format,
&stdin_used,
&program_ref)) {
fprintf(stderr, "error: invalid program-ref\n");
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
{
amduat_asl_store_error_t err =
amduat_asl_store_get(&store, program_ref, &artifact);
if (err != AMDUAT_ASL_STORE_OK) {
fprintf(stderr, "error: store get failed: %s\n",
amduat_pel_cli_store_error_str(err));
amduat_pel_cli_free_reference(&program_ref);
return amduat_pel_cli_map_store_error(err);
}
}
amduat_pel_cli_free_reference(&program_ref);
} else {
uint8_t *bytes = NULL;
size_t len = 0;
if (!amduat_pel_cli_read_path_once(input_path,
&stdin_used,
&bytes,
&len)) {
fprintf(stderr, "error: failed to read input\n");
return AMDUAT_PEL_CLI_EXIT_IO;
}
if (!amduat_asl_artifact_from_bytes(amduat_octets(bytes, len),
input_format,
false,
amduat_type_tag(0),
&artifact)) {
free(bytes);
fprintf(stderr, "error: invalid artifact encoding\n");
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
if (input_format == AMDUAT_ASL_IO_ARTIFACT) {
free(bytes);
}
}
if (has_expect_type_tag) {
if (!amduat_asl_artifact_expect_type_tag(&artifact, expect_type_tag)) {
fprintf(stderr, "error: type-tag mismatch\n");
amduat_asl_artifact_free(&artifact);
return AMDUAT_PEL_CLI_EXIT_UNSUPPORTED;
}
}
if (artifact.has_type_tag &&
artifact.type_tag.tag_id != AMDUAT_PEL_TYPE_TAG_PROGRAM_DAG_1) {
fprintf(stderr, "error: type-tag mismatch\n");
amduat_asl_artifact_free(&artifact);
return AMDUAT_PEL_CLI_EXIT_UNSUPPORTED;
}
memset(&program, 0, sizeof(program));
if (!amduat_pel_program_decode_artifact(&artifact, &program)) {
fprintf(stderr, "error: invalid program encoding\n");
amduat_asl_artifact_free(&artifact);
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
if (!amduat_format_pel_program(stdout, &program, format)) {
fprintf(stderr, "error: failed to format program\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
} else if (format == AMDUAT_FORMAT_OUTPUT_JSON) {
fputc('\n', stdout);
}
amduat_enc_pel_program_dag_free(&program);
amduat_asl_artifact_free(&artifact);
return exit_code;
}
static int amduat_pel_cli_cmd_program_normalize(
int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
const char *input_path = "-";
const char *output_path = "-";
amduat_asl_io_format_t input_format = AMDUAT_ASL_IO_RAW;
amduat_asl_io_format_t output_format = AMDUAT_ASL_IO_RAW;
bool has_type_tag = false;
amduat_type_tag_t type_tag;
amduat_artifact_t artifact;
amduat_pel_program_t program;
amduat_octets_t normalized;
bool stdin_used = false;
int exit_code = AMDUAT_PEL_CLI_EXIT_OK;
int i;
(void)global;
for (i = 0; i < argc; ++i) {
if (strcmp(argv[i], "--input") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --input requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
input_path = argv[++i];
} else if (strcmp(argv[i], "--input-format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --input-format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_asl_io_format_parse(argv[++i], &input_format)) {
fprintf(stderr, "error: invalid input-format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--output") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --output requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
output_path = argv[++i];
} else if (strcmp(argv[i], "--output-format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --output-format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_asl_io_format_parse(argv[++i], &output_format)) {
fprintf(stderr, "error: invalid output-format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--type-tag") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --type-tag requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_asl_parse_type_tag(argv[++i], &type_tag)) {
fprintf(stderr, "error: invalid type-tag\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
has_type_tag = true;
} else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
amduat_pel_cli_print_usage(stdout);
return AMDUAT_PEL_CLI_EXIT_OK;
} else {
fprintf(stderr, "error: unknown option: %s\n", argv[i]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
}
memset(&artifact, 0, sizeof(artifact));
{
uint8_t *bytes = NULL;
size_t len = 0;
if (!amduat_pel_cli_read_path_once(input_path,
&stdin_used,
&bytes,
&len)) {
fprintf(stderr, "error: failed to read input\n");
return AMDUAT_PEL_CLI_EXIT_IO;
}
if (!amduat_asl_artifact_from_bytes(amduat_octets(bytes, len),
input_format,
false,
amduat_type_tag(0),
&artifact)) {
free(bytes);
fprintf(stderr, "error: invalid artifact encoding\n");
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
if (input_format == AMDUAT_ASL_IO_ARTIFACT) {
free(bytes);
}
}
memset(&program, 0, sizeof(program));
if (artifact.has_type_tag &&
artifact.type_tag.tag_id != AMDUAT_PEL_TYPE_TAG_PROGRAM_DAG_1) {
fprintf(stderr, "error: type-tag mismatch\n");
amduat_asl_artifact_free(&artifact);
return AMDUAT_PEL_CLI_EXIT_UNSUPPORTED;
}
if (!amduat_pel_program_decode_artifact(&artifact, &program)) {
fprintf(stderr, "error: invalid program encoding\n");
amduat_asl_artifact_free(&artifact);
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
normalized = amduat_octets(NULL, 0);
if (!amduat_enc_pel_program_dag_encode_v1(&program, &normalized)) {
fprintf(stderr, "error: failed to normalize program\n");
amduat_enc_pel_program_dag_free(&program);
amduat_asl_artifact_free(&artifact);
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
if (output_format == AMDUAT_ASL_IO_RAW) {
if (!amduat_asl_write_path(output_path,
normalized.data,
normalized.len)) {
fprintf(stderr, "error: failed to write output\n");
exit_code = AMDUAT_PEL_CLI_EXIT_IO;
}
} else {
amduat_type_tag_t tag =
has_type_tag ? type_tag
: (artifact.has_type_tag
? artifact.type_tag
: amduat_type_tag(AMDUAT_PEL_TYPE_TAG_PROGRAM_DAG_1));
amduat_artifact_t out_artifact =
amduat_artifact_with_type(normalized, tag);
amduat_octets_t encoded;
if (!amduat_enc_asl1_core_encode_artifact_v1(out_artifact, &encoded)) {
fprintf(stderr, "error: failed to encode output artifact\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
} else {
if (!amduat_asl_write_path(output_path, encoded.data, encoded.len)) {
fprintf(stderr, "error: failed to write output\n");
exit_code = AMDUAT_PEL_CLI_EXIT_IO;
}
free((void *)encoded.data);
}
}
free((void *)normalized.data);
amduat_enc_pel_program_dag_free(&program);
amduat_asl_artifact_free(&artifact);
return exit_code;
}
static int amduat_pel_cli_cmd_program(
int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
if (argc < 1) {
fprintf(stderr, "error: program requires a subcommand\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (strcmp(argv[0], "decode") == 0) {
return amduat_pel_cli_cmd_program_decode(argc - 1, argv + 1, global);
}
if (strcmp(argv[0], "normalize") == 0) {
return amduat_pel_cli_cmd_program_normalize(argc - 1, argv + 1, global);
}
fprintf(stderr, "error: unknown program subcommand: %s\n", argv[0]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
static int amduat_pel_cli_cmd_trace_decode(
int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
const char *input_path = "-";
const char *trace_ref_text = NULL;
bool input_path_set = false;
amduat_asl_io_format_t input_format = AMDUAT_ASL_IO_RAW;
amduat_format_output_t format;
amduat_format_ref_format_t ref_format;
const char *root;
bool has_expect_type_tag = false;
amduat_type_tag_t expect_type_tag;
amduat_asl_store_fs_config_t cfg;
amduat_asl_store_fs_t fs;
amduat_asl_store_t store;
amduat_reference_t trace_ref;
amduat_artifact_t artifact;
amduat_pel_trace_dag_value_t trace;
bool stdin_used = false;
int exit_code = AMDUAT_PEL_CLI_EXIT_OK;
int i;
if (global == NULL) {
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
format = global->format;
ref_format = global->ref_format;
root = global->root;
for (i = 0; i < argc; ++i) {
if (strcmp(argv[i], "--input") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --input requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
input_path = argv[++i];
input_path_set = true;
} else if (strcmp(argv[i], "--trace-ref") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --trace-ref requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
trace_ref_text = argv[++i];
} else if (strcmp(argv[i], "--input-format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --input-format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_asl_io_format_parse(argv[++i], &input_format)) {
fprintf(stderr, "error: invalid input-format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--expect-type-tag") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --expect-type-tag requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_asl_parse_type_tag(argv[++i], &expect_type_tag)) {
fprintf(stderr, "error: invalid expect-type-tag\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
has_expect_type_tag = true;
} else if (strcmp(argv[i], "--format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_output_parse(argv[++i], &format)) {
fprintf(stderr, "error: invalid format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--ref-format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --ref-format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_ref_parse(argv[++i], &ref_format)) {
fprintf(stderr, "error: invalid ref-format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--root") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --root requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
root = argv[++i];
} else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
amduat_pel_cli_print_usage(stdout);
return AMDUAT_PEL_CLI_EXIT_OK;
} else {
fprintf(stderr, "error: unknown option: %s\n", argv[i]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
}
if (trace_ref_text != NULL && input_path_set) {
fprintf(stderr, "error: use --input or --trace-ref\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
memset(&artifact, 0, sizeof(artifact));
if (trace_ref_text != NULL) {
if (!amduat_asl_store_fs_load_config(root, &cfg)) {
fprintf(stderr, "error: failed to load store config: %s\n", root);
return AMDUAT_PEL_CLI_EXIT_CONFIG;
}
if (!amduat_asl_store_fs_init(&fs, cfg.config, root)) {
fprintf(stderr, "error: failed to initialize store\n");
return AMDUAT_PEL_CLI_EXIT_CONFIG;
}
amduat_asl_store_init(&store, cfg.config, amduat_asl_store_fs_ops(), &fs);
if (!amduat_pel_cli_ref_from_text(trace_ref_text,
ref_format,
&stdin_used,
&trace_ref)) {
fprintf(stderr, "error: invalid trace-ref\n");
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
{
amduat_asl_store_error_t err =
amduat_asl_store_get(&store, trace_ref, &artifact);
if (err != AMDUAT_ASL_STORE_OK) {
fprintf(stderr, "error: store get failed: %s\n",
amduat_pel_cli_store_error_str(err));
amduat_pel_cli_free_reference(&trace_ref);
return amduat_pel_cli_map_store_error(err);
}
}
amduat_pel_cli_free_reference(&trace_ref);
} else {
uint8_t *bytes = NULL;
size_t len = 0;
if (!amduat_pel_cli_read_path_once(input_path,
&stdin_used,
&bytes,
&len)) {
fprintf(stderr, "error: failed to read input\n");
return AMDUAT_PEL_CLI_EXIT_IO;
}
if (!amduat_asl_artifact_from_bytes(amduat_octets(bytes, len),
input_format,
false,
amduat_type_tag(0),
&artifact)) {
free(bytes);
fprintf(stderr, "error: invalid artifact encoding\n");
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
if (input_format == AMDUAT_ASL_IO_ARTIFACT) {
free(bytes);
}
}
if (has_expect_type_tag) {
if (!amduat_asl_artifact_expect_type_tag(&artifact, expect_type_tag)) {
fprintf(stderr, "error: type-tag mismatch\n");
amduat_asl_artifact_free(&artifact);
return AMDUAT_PEL_CLI_EXIT_UNSUPPORTED;
}
}
if (artifact.has_type_tag &&
artifact.type_tag.tag_id != AMDUAT_TYPE_TAG_PEL_TRACE_DAG_1) {
fprintf(stderr, "error: type-tag mismatch\n");
amduat_asl_artifact_free(&artifact);
return AMDUAT_PEL_CLI_EXIT_UNSUPPORTED;
}
memset(&trace, 0, sizeof(trace));
if (!amduat_pel_trace_decode_artifact(&artifact, &trace)) {
fprintf(stderr, "error: invalid trace encoding\n");
amduat_asl_artifact_free(&artifact);
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
if (!amduat_format_pel_trace(stdout, &trace, format, ref_format)) {
fprintf(stderr, "error: failed to format trace\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
} else if (format == AMDUAT_FORMAT_OUTPUT_JSON) {
fputc('\n', stdout);
}
amduat_enc_pel_trace_dag_free(&trace);
amduat_asl_artifact_free(&artifact);
return exit_code;
}
static int amduat_pel_cli_cmd_trace_from_result(
int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
const char *result_ref_text = NULL;
amduat_format_output_t format;
amduat_format_ref_format_t ref_format;
const char *root;
amduat_asl_store_fs_config_t cfg;
amduat_asl_store_fs_t fs;
amduat_asl_store_t store;
amduat_reference_t result_ref;
amduat_artifact_t artifact;
amduat_pel_surface_execution_result_t result;
bool stdin_used = false;
int exit_code = AMDUAT_PEL_CLI_EXIT_OK;
int i;
if (global == NULL) {
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
format = global->format;
ref_format = global->ref_format;
root = global->root;
for (i = 0; i < argc; ++i) {
if (strcmp(argv[i], "--result-ref") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --result-ref requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
result_ref_text = argv[++i];
} else if (strcmp(argv[i], "--format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_output_parse(argv[++i], &format)) {
fprintf(stderr, "error: invalid format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--ref-format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --ref-format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_ref_parse(argv[++i], &ref_format)) {
fprintf(stderr, "error: invalid ref-format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--root") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --root requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
root = argv[++i];
} else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
amduat_pel_cli_print_usage(stdout);
return AMDUAT_PEL_CLI_EXIT_OK;
} else {
fprintf(stderr, "error: unknown option: %s\n", argv[i]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
}
if (result_ref_text == NULL) {
fprintf(stderr, "error: --result-ref is required\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_asl_store_fs_load_config(root, &cfg)) {
fprintf(stderr, "error: failed to load store config: %s\n", root);
return AMDUAT_PEL_CLI_EXIT_CONFIG;
}
if (!amduat_asl_store_fs_init(&fs, cfg.config, root)) {
fprintf(stderr, "error: failed to initialize store\n");
return AMDUAT_PEL_CLI_EXIT_CONFIG;
}
amduat_asl_store_init(&store, cfg.config, amduat_asl_store_fs_ops(), &fs);
if (!amduat_pel_cli_ref_from_text(result_ref_text,
ref_format,
&stdin_used,
&result_ref)) {
fprintf(stderr, "error: invalid result-ref\n");
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
memset(&artifact, 0, sizeof(artifact));
{
amduat_asl_store_error_t err =
amduat_asl_store_get(&store, result_ref, &artifact);
if (err != AMDUAT_ASL_STORE_OK) {
fprintf(stderr, "error: store get failed: %s\n",
amduat_pel_cli_store_error_str(err));
amduat_pel_cli_free_reference(&result_ref);
return amduat_pel_cli_map_store_error(err);
}
}
memset(&result, 0, sizeof(result));
if (artifact.has_type_tag &&
artifact.type_tag.tag_id != AMDUAT_TYPE_TAG_PEL1_RESULT_1) {
fprintf(stderr, "error: type-tag mismatch\n");
amduat_pel_cli_free_reference(&result_ref);
amduat_asl_artifact_free(&artifact);
return AMDUAT_PEL_CLI_EXIT_UNSUPPORTED;
}
if (!amduat_pel_result_decode_artifact(&artifact, &result)) {
fprintf(stderr, "error: invalid result encoding\n");
amduat_pel_cli_free_reference(&result_ref);
amduat_asl_artifact_free(&artifact);
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
if (format == AMDUAT_FORMAT_OUTPUT_TEXT) {
fprintf(stdout, "has_trace_ref=%s\n",
result.has_trace_ref ? "true" : "false");
fprintf(stdout, "trace_ref=");
if (result.has_trace_ref) {
if (!amduat_format_ref_write_text(stdout,
result.trace_ref,
ref_format)) {
fprintf(stderr, "error: failed to encode trace ref\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
}
}
fputc('\n', stdout);
} else {
fputs("{\"has_trace_ref\":", stdout);
fputs(result.has_trace_ref ? "true" : "false", stdout);
fputs(",\"trace_ref\":", stdout);
if (result.has_trace_ref) {
if (!amduat_format_ref_write_json(stdout,
result.trace_ref,
ref_format)) {
fprintf(stderr, "error: failed to encode trace ref\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
}
} else {
fputs("null", stdout);
}
fputs("}\n", stdout);
}
amduat_enc_pel1_result_free(&result);
amduat_pel_cli_free_reference(&result_ref);
amduat_asl_artifact_free(&artifact);
return exit_code;
}
static int amduat_pel_cli_cmd_trace(
int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
if (argc < 1) {
fprintf(stderr, "error: trace requires a subcommand\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (strcmp(argv[0], "decode") == 0) {
return amduat_pel_cli_cmd_trace_decode(argc - 1, argv + 1, global);
}
if (strcmp(argv[0], "from-result") == 0) {
return amduat_pel_cli_cmd_trace_from_result(argc - 1, argv + 1, global);
}
fprintf(stderr, "error: unknown trace subcommand: %s\n", argv[0]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
static int amduat_pel_cli_cmd_result_decode(
int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
const char *input_path = "-";
const char *result_ref_text = NULL;
bool input_path_set = false;
amduat_asl_io_format_t input_format = AMDUAT_ASL_IO_RAW;
amduat_format_output_t format;
amduat_format_ref_format_t ref_format;
const char *root;
bool has_expect_type_tag = false;
amduat_type_tag_t expect_type_tag;
amduat_asl_store_fs_config_t cfg;
amduat_asl_store_fs_t fs;
amduat_asl_store_t store;
amduat_reference_t result_ref;
amduat_artifact_t artifact;
amduat_pel_surface_execution_result_t result;
bool stdin_used = false;
int exit_code = AMDUAT_PEL_CLI_EXIT_OK;
int i;
if (global == NULL) {
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
format = global->format;
ref_format = global->ref_format;
root = global->root;
for (i = 0; i < argc; ++i) {
if (strcmp(argv[i], "--input") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --input requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
input_path = argv[++i];
input_path_set = true;
} else if (strcmp(argv[i], "--result-ref") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --result-ref requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
result_ref_text = argv[++i];
} else if (strcmp(argv[i], "--input-format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --input-format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_asl_io_format_parse(argv[++i], &input_format)) {
fprintf(stderr, "error: invalid input-format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--expect-type-tag") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --expect-type-tag requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_asl_parse_type_tag(argv[++i], &expect_type_tag)) {
fprintf(stderr, "error: invalid expect-type-tag\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
has_expect_type_tag = true;
} else if (strcmp(argv[i], "--format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_output_parse(argv[++i], &format)) {
fprintf(stderr, "error: invalid format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--ref-format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --ref-format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_ref_parse(argv[++i], &ref_format)) {
fprintf(stderr, "error: invalid ref-format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--root") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --root requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
root = argv[++i];
} else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
amduat_pel_cli_print_usage(stdout);
return AMDUAT_PEL_CLI_EXIT_OK;
} else {
fprintf(stderr, "error: unknown option: %s\n", argv[i]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
}
if (result_ref_text != NULL && input_path_set) {
fprintf(stderr, "error: use --input or --result-ref\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
memset(&artifact, 0, sizeof(artifact));
if (result_ref_text != NULL) {
if (!amduat_asl_store_fs_load_config(root, &cfg)) {
fprintf(stderr, "error: failed to load store config: %s\n", root);
return AMDUAT_PEL_CLI_EXIT_CONFIG;
}
if (!amduat_asl_store_fs_init(&fs, cfg.config, root)) {
fprintf(stderr, "error: failed to initialize store\n");
return AMDUAT_PEL_CLI_EXIT_CONFIG;
}
amduat_asl_store_init(&store, cfg.config, amduat_asl_store_fs_ops(), &fs);
if (!amduat_pel_cli_ref_from_text(result_ref_text,
ref_format,
&stdin_used,
&result_ref)) {
fprintf(stderr, "error: invalid result-ref\n");
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
{
amduat_asl_store_error_t err =
amduat_asl_store_get(&store, result_ref, &artifact);
if (err != AMDUAT_ASL_STORE_OK) {
fprintf(stderr, "error: store get failed: %s\n",
amduat_pel_cli_store_error_str(err));
amduat_pel_cli_free_reference(&result_ref);
return amduat_pel_cli_map_store_error(err);
}
}
amduat_pel_cli_free_reference(&result_ref);
} else {
uint8_t *bytes = NULL;
size_t len = 0;
if (!amduat_pel_cli_read_path_once(input_path,
&stdin_used,
&bytes,
&len)) {
fprintf(stderr, "error: failed to read input\n");
return AMDUAT_PEL_CLI_EXIT_IO;
}
if (!amduat_asl_artifact_from_bytes(amduat_octets(bytes, len),
input_format,
false,
amduat_type_tag(0),
&artifact)) {
free(bytes);
fprintf(stderr, "error: invalid artifact encoding\n");
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
if (input_format == AMDUAT_ASL_IO_ARTIFACT) {
free(bytes);
}
}
if (has_expect_type_tag) {
if (!amduat_asl_artifact_expect_type_tag(&artifact, expect_type_tag)) {
fprintf(stderr, "error: type-tag mismatch\n");
amduat_asl_artifact_free(&artifact);
return AMDUAT_PEL_CLI_EXIT_UNSUPPORTED;
}
}
if (artifact.has_type_tag &&
artifact.type_tag.tag_id != AMDUAT_TYPE_TAG_PEL1_RESULT_1) {
fprintf(stderr, "error: type-tag mismatch\n");
amduat_asl_artifact_free(&artifact);
return AMDUAT_PEL_CLI_EXIT_UNSUPPORTED;
}
memset(&result, 0, sizeof(result));
if (!amduat_pel_result_decode_artifact(&artifact, &result)) {
fprintf(stderr, "error: invalid result encoding\n");
amduat_asl_artifact_free(&artifact);
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
if (!amduat_format_pel_result(stdout, &result, format, ref_format)) {
fprintf(stderr, "error: failed to format result\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
} else if (format == AMDUAT_FORMAT_OUTPUT_JSON) {
fputc('\n', stdout);
}
amduat_enc_pel1_result_free(&result);
amduat_asl_artifact_free(&artifact);
return exit_code;
}
static int amduat_pel_cli_cmd_result(
int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
if (argc < 1) {
fprintf(stderr, "error: result requires a subcommand\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (strcmp(argv[0], "decode") == 0) {
return amduat_pel_cli_cmd_result_decode(argc - 1, argv + 1, global);
}
fprintf(stderr, "error: unknown result subcommand: %s\n", argv[0]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
static int amduat_pel_cli_cmd_op_list(
int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
amduat_format_output_t format;
const amduat_pel_kernel_op_desc_t *descs;
size_t descs_len = 0;
size_t i;
if (global == NULL) {
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
format = global->format;
for (i = 0; i < (size_t)argc; ++i) {
if (strcmp(argv[i], "--format") == 0) {
if (i + 1 >= (size_t)argc) {
fprintf(stderr, "error: --format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_output_parse(argv[++i], &format)) {
fprintf(stderr, "error: invalid format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--help") == 0 ||
strcmp(argv[i], "-h") == 0) {
amduat_pel_cli_print_usage(stdout);
return AMDUAT_PEL_CLI_EXIT_OK;
} else {
fprintf(stderr, "error: unknown option: %s\n", argv[i]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
}
descs = amduat_pel_kernel_op_descs(&descs_len);
if (format == AMDUAT_FORMAT_OUTPUT_TEXT) {
for (i = 0; i < descs_len; ++i) {
const char *name = amduat_pel_kernel_op_name(descs[i].kind);
if (name == NULL) {
continue;
}
fprintf(stdout, "name=%s version=1\n", name);
}
} else {
bool first = true;
fputs("{\"ops\":[", stdout);
for (i = 0; i < descs_len; ++i) {
const char *name = amduat_pel_kernel_op_name(descs[i].kind);
if (name == NULL) {
continue;
}
if (!first) {
fputc(',', stdout);
}
first = false;
fprintf(stdout, "{\"name\":");
amduat_format_json_escape(stdout,
amduat_octets(name, strlen(name)));
fprintf(stdout, ",\"version\":1}");
}
fputs("]}\n", stdout);
}
return AMDUAT_PEL_CLI_EXIT_OK;
}
static int amduat_pel_cli_cmd_op_describe(
int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
const char *op_text = NULL;
amduat_octets_t op_name;
uint32_t op_version = 1;
amduat_format_output_t format;
const amduat_pel_kernel_op_desc_t *desc;
int i;
if (global == NULL) {
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
format = global->format;
for (i = 0; i < argc; ++i) {
if (strcmp(argv[i], "--format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_output_parse(argv[++i], &format)) {
fprintf(stderr, "error: invalid format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--help") == 0 ||
strcmp(argv[i], "-h") == 0) {
amduat_pel_cli_print_usage(stdout);
return AMDUAT_PEL_CLI_EXIT_OK;
} else if (op_text == NULL) {
op_text = argv[i];
} else {
fprintf(stderr, "error: unexpected argument: %s\n", argv[i]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
}
if (op_text == NULL) {
fprintf(stderr, "error: NAME[=VERSION] is required\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
op_name = amduat_octets(NULL, 0);
if (!amduat_pel_op_parse_name(op_text, &op_name, &op_version)) {
fprintf(stderr, "error: invalid op name\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
desc = amduat_pel_kernel_op_lookup(op_name, op_version);
if (desc == NULL) {
fprintf(stderr, "error: op not found\n");
return AMDUAT_PEL_CLI_EXIT_NOT_FOUND;
}
if (!amduat_format_pel_op_desc(stdout,
desc,
op_name,
op_version,
format)) {
fprintf(stderr, "error: failed to format op description\n");
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
return AMDUAT_PEL_CLI_EXIT_OK;
}
static int amduat_pel_cli_cmd_op_params_decode(
int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
const char *op_text = NULL;
amduat_octets_t op_name;
uint32_t op_version = 1;
const char *input_path = NULL;
amduat_format_output_t format;
const amduat_pel_kernel_op_desc_t *desc;
amduat_pel_kernel_params_t params;
uint8_t *bytes = NULL;
size_t len = 0;
bool stdin_used = false;
int exit_code = AMDUAT_PEL_CLI_EXIT_OK;
int i;
if (global == NULL) {
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
format = global->format;
for (i = 0; i < argc; ++i) {
if (strcmp(argv[i], "--op") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --op requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
op_text = argv[++i];
} else if (strcmp(argv[i], "--input") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --input requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
input_path = argv[++i];
} else if (strcmp(argv[i], "--format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_output_parse(argv[++i], &format)) {
fprintf(stderr, "error: invalid format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--help") == 0 ||
strcmp(argv[i], "-h") == 0) {
amduat_pel_cli_print_usage(stdout);
return AMDUAT_PEL_CLI_EXIT_OK;
} else {
fprintf(stderr, "error: unknown option: %s\n", argv[i]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
}
if (op_text == NULL || input_path == NULL) {
fprintf(stderr, "error: --op and --input are required\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
op_name = amduat_octets(NULL, 0);
if (!amduat_pel_op_parse_name(op_text, &op_name, &op_version)) {
fprintf(stderr, "error: invalid op name\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
desc = amduat_pel_kernel_op_lookup(op_name, op_version);
if (desc == NULL) {
fprintf(stderr, "error: op not found\n");
return AMDUAT_PEL_CLI_EXIT_NOT_FOUND;
}
if (!amduat_pel_cli_read_path_once(input_path,
&stdin_used,
&bytes,
&len)) {
fprintf(stderr, "error: failed to read input\n");
return AMDUAT_PEL_CLI_EXIT_IO;
}
if (!amduat_pel_kernel_params_decode(
desc, amduat_octets(bytes, len), &params)) {
fprintf(stderr, "error: failed to decode params\n");
free(bytes);
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
if (!amduat_format_pel_op_params(stdout,
&params,
op_name,
op_version,
format)) {
fprintf(stderr, "error: failed to format params\n");
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
}
free(bytes);
return exit_code;
}
static int amduat_pel_cli_cmd_op(
int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
if (argc < 1) {
fprintf(stderr, "error: op requires a subcommand\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (strcmp(argv[0], "list") == 0) {
return amduat_pel_cli_cmd_op_list(argc - 1, argv + 1, global);
}
if (strcmp(argv[0], "describe") == 0) {
return amduat_pel_cli_cmd_op_describe(argc - 1, argv + 1, global);
}
if (strcmp(argv[0], "params-decode") == 0) {
return amduat_pel_cli_cmd_op_params_decode(argc - 1, argv + 1, global);
}
fprintf(stderr, "error: unknown op subcommand: %s\n", argv[0]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
static int amduat_pel_cli_cmd_scheme_show(
int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
amduat_format_output_t format;
amduat_format_ref_format_t ref_format;
amduat_reference_t scheme_ref;
int i;
if (global == NULL) {
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
format = global->format;
ref_format = global->ref_format;
for (i = 0; i < argc; ++i) {
if (strcmp(argv[i], "--format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_output_parse(argv[++i], &format)) {
fprintf(stderr, "error: invalid format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--ref-format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --ref-format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_ref_parse(argv[++i], &ref_format)) {
fprintf(stderr, "error: invalid ref-format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--help") == 0 ||
strcmp(argv[i], "-h") == 0) {
amduat_pel_cli_print_usage(stdout);
return AMDUAT_PEL_CLI_EXIT_OK;
} else {
fprintf(stderr, "error: unknown option: %s\n", argv[i]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
}
scheme_ref = amduat_pel_program_dag_scheme_ref();
if (format == AMDUAT_FORMAT_OUTPUT_TEXT) {
fprintf(stdout, "scheme_ref=");
if (!amduat_format_ref_write_text(stdout, scheme_ref, ref_format)) {
fprintf(stderr, "error: failed to encode scheme ref\n");
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
fputc('\n', stdout);
fprintf(stdout, "program_type_tag=0x%08x\n",
AMDUAT_PEL_TYPE_TAG_PROGRAM_DAG_1);
fprintf(stdout, "trace_type_tag=0x%08x\n",
AMDUAT_TYPE_TAG_PEL_TRACE_DAG_1);
fprintf(stdout, "result_type_tag=0x%08x\n",
AMDUAT_TYPE_TAG_PEL1_RESULT_1);
fprintf(stdout, "program_profile_id=0x%04x\n",
AMDUAT_PEL_ENC_PROGRAM_DAG_V1);
fprintf(stdout, "trace_profile_id=0x%04x\n",
AMDUAT_PEL_ENC_TRACE_DAG_V1);
fprintf(stdout, "result_profile_id=0x%04x\n",
AMDUAT_PEL_ENC_EXECUTION_RESULT_V1);
} else {
fputs("{\"scheme_ref\":", stdout);
if (!amduat_format_ref_write_json(stdout, scheme_ref, ref_format)) {
fprintf(stderr, "error: failed to encode scheme ref\n");
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
fprintf(stdout, ",\"program_type_tag\":%u",
AMDUAT_PEL_TYPE_TAG_PROGRAM_DAG_1);
fprintf(stdout, ",\"trace_type_tag\":%u",
AMDUAT_TYPE_TAG_PEL_TRACE_DAG_1);
fprintf(stdout, ",\"result_type_tag\":%u",
AMDUAT_TYPE_TAG_PEL1_RESULT_1);
fprintf(stdout, ",\"program_profile_id\":%u",
AMDUAT_PEL_ENC_PROGRAM_DAG_V1);
fprintf(stdout, ",\"trace_profile_id\":%u",
AMDUAT_PEL_ENC_TRACE_DAG_V1);
fprintf(stdout, ",\"result_profile_id\":%u}\n",
AMDUAT_PEL_ENC_EXECUTION_RESULT_V1);
}
return AMDUAT_PEL_CLI_EXIT_OK;
}
static int amduat_pel_cli_cmd_scheme_dag_ref(int argc, char **argv) {
amduat_format_ref_format_t fmt = AMDUAT_FORMAT_REF_HEX;
amduat_reference_t scheme_ref;
int i;
for (i = 0; i < argc; ++i) {
if (strcmp(argv[i], "--format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_ref_parse(argv[++i], &fmt)) {
fprintf(stderr, "error: invalid format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--help") == 0 ||
strcmp(argv[i], "-h") == 0) {
amduat_pel_cli_print_usage(stdout);
return AMDUAT_PEL_CLI_EXIT_OK;
} else {
fprintf(stderr, "error: unknown option: %s\n", argv[i]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
}
scheme_ref = amduat_pel_program_dag_scheme_ref();
if (fmt == AMDUAT_FORMAT_REF_HEX) {
char *text = NULL;
if (!amduat_asl_ref_encode_hex(scheme_ref, &text)) {
fprintf(stderr, "error: failed to encode scheme ref\n");
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
fputs(text, stdout);
fputc('\n', stdout);
free(text);
} else {
amduat_octets_t encoded;
if (!amduat_enc_asl1_core_encode_reference_v1(scheme_ref, &encoded)) {
fprintf(stderr, "error: failed to encode scheme ref\n");
return AMDUAT_PEL_CLI_EXIT_CODEC;
}
if (!amduat_asl_write_stream(stdout, encoded.data, encoded.len)) {
fprintf(stderr, "error: failed to write scheme ref\n");
free((void *)encoded.data);
return AMDUAT_PEL_CLI_EXIT_IO;
}
free((void *)encoded.data);
}
return AMDUAT_PEL_CLI_EXIT_OK;
}
static int amduat_pel_cli_cmd_scheme(
int argc,
char **argv,
const amduat_pel_cli_global_opts_t *global) {
if (argc < 1) {
fprintf(stderr, "error: scheme requires a subcommand\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (strcmp(argv[0], "show") == 0) {
return amduat_pel_cli_cmd_scheme_show(argc - 1, argv + 1, global);
}
if (strcmp(argv[0], "dag-ref") == 0) {
return amduat_pel_cli_cmd_scheme_dag_ref(argc - 1, argv + 1);
}
fprintf(stderr, "error: unknown scheme subcommand: %s\n", argv[0]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
static int amduat_pel_cli_cmd_help(int argc, char **argv) {
(void)argc;
(void)argv;
amduat_pel_cli_print_usage(stdout);
return AMDUAT_PEL_CLI_EXIT_OK;
}
int main(int argc, char **argv) {
amduat_pel_cli_global_opts_t global;
const char *command = NULL;
int i;
memset(&global, 0, sizeof(global));
global.root = AMDUAT_PEL_CLI_DEFAULT_ROOT;
global.ref_format = AMDUAT_FORMAT_REF_HEX;
global.format = AMDUAT_FORMAT_OUTPUT_TEXT;
global.quiet = false;
for (i = 1; i < argc; ++i) {
if (argv[i][0] != '-') {
command = argv[i];
++i;
break;
}
if (strcmp(argv[i], "--root") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --root requires a path\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
global.root = argv[++i];
} else if (strcmp(argv[i], "--ref-format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --ref-format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_ref_parse(argv[++i], &global.ref_format)) {
fprintf(stderr, "error: invalid ref-format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--format") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "error: --format requires a value\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (!amduat_format_output_parse(argv[++i], &global.format)) {
fprintf(stderr, "error: invalid format\n");
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
} else if (strcmp(argv[i], "--quiet") == 0) {
global.quiet = true;
} else if (strcmp(argv[i], "--help") == 0 ||
strcmp(argv[i], "-h") == 0) {
amduat_pel_cli_print_usage(stdout);
return AMDUAT_PEL_CLI_EXIT_OK;
} else {
fprintf(stderr, "error: unknown option: %s\n", argv[i]);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
}
if (command == NULL) {
fprintf(stderr, "error: command required\n");
amduat_pel_cli_print_usage(stderr);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}
if (strcmp(command, "run") == 0) {
return amduat_pel_cli_cmd_run(argc - i, argv + i, &global);
}
if (strcmp(command, "exec") == 0) {
return amduat_pel_cli_cmd_exec(argc - i, argv + i, &global);
}
if (strcmp(command, "validate") == 0) {
return amduat_pel_cli_cmd_validate(argc - i, argv + i, &global);
}
if (strcmp(command, "program") == 0) {
return amduat_pel_cli_cmd_program(argc - i, argv + i, &global);
}
if (strcmp(command, "trace") == 0) {
return amduat_pel_cli_cmd_trace(argc - i, argv + i, &global);
}
if (strcmp(command, "result") == 0) {
return amduat_pel_cli_cmd_result(argc - i, argv + i, &global);
}
if (strcmp(command, "op") == 0) {
return amduat_pel_cli_cmd_op(argc - i, argv + i, &global);
}
if (strcmp(command, "scheme") == 0) {
return amduat_pel_cli_cmd_scheme(argc - i, argv + i, &global);
}
if (strcmp(command, "help") == 0) {
return amduat_pel_cli_cmd_help(argc - i, argv + i);
}
fprintf(stderr, "error: unknown command: %s\n", command);
amduat_pel_cli_print_usage(stderr);
return AMDUAT_PEL_CLI_EXIT_USAGE;
}