#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 #include #include #include #include #include #include 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] [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 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, ¶ms_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(¶ms_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(¶ms_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), ¶ms)) { fprintf(stderr, "error: failed to decode params\n"); free(bytes); return AMDUAT_PEL_CLI_EXIT_CODEC; } if (!amduat_format_pel_op_params(stdout, ¶ms, 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; }