Add PEL collection view projection
This commit is contained in:
parent
3e526975ce
commit
d9122b53bb
|
|
@ -62,6 +62,8 @@ set(AMDUAT_UTIL_SRCS
|
||||||
|
|
||||||
set(AMDUAT_ASL_SRCS
|
set(AMDUAT_ASL_SRCS
|
||||||
src/kernel/asl/core.c
|
src/kernel/asl/core.c
|
||||||
|
src/near_core/asl/collection_view.c
|
||||||
|
src/near_core/asl/none.c
|
||||||
src/near_core/asl/artifact_io.c
|
src/near_core/asl/artifact_io.c
|
||||||
src/near_core/asl/io.c
|
src/near_core/asl/io.c
|
||||||
src/near_core/asl/index_accel.c
|
src/near_core/asl/index_accel.c
|
||||||
|
|
@ -127,6 +129,7 @@ set(AMDUAT_PEL_SRCS
|
||||||
src/pel_stack/trace_dag/trace_dag.c
|
src/pel_stack/trace_dag/trace_dag.c
|
||||||
src/pel_stack/queue/queue.c
|
src/pel_stack/queue/queue.c
|
||||||
src/pel_stack/opreg/kernel.c
|
src/pel_stack/opreg/kernel.c
|
||||||
|
src/pel_stack/opreg/kernel_collection.c
|
||||||
src/pel_stack/opreg/kernel_params.c
|
src/pel_stack/opreg/kernel_params.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -193,7 +196,8 @@ amduat_add_lib(format SRCS ${AMDUAT_FORMAT_SRCS})
|
||||||
amduat_link(format amduat_asl amduat_enc amduat_util)
|
amduat_link(format amduat_asl amduat_enc amduat_util)
|
||||||
|
|
||||||
amduat_add_lib(pel SRCS ${AMDUAT_PEL_SRCS})
|
amduat_add_lib(pel SRCS ${AMDUAT_PEL_SRCS})
|
||||||
amduat_link(pel amduat_asl_materialization_cache_fs amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
|
amduat_link(pel amduat_asl_materialization_cache_fs amduat_asl_collection
|
||||||
|
amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
|
||||||
|
|
||||||
amduat_add_lib(tgk SRCS ${AMDUAT_TGK_SRCS})
|
amduat_add_lib(tgk SRCS ${AMDUAT_TGK_SRCS})
|
||||||
amduat_link(tgk amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
|
amduat_link(tgk amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,12 @@ typedef struct {
|
||||||
amduat_asl_pointer_store_t pointer_store;
|
amduat_asl_pointer_store_t pointer_store;
|
||||||
} amduat_asl_collection_store_t;
|
} amduat_asl_collection_store_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t snapshot_offset;
|
||||||
|
amduat_reference_t *refs;
|
||||||
|
size_t refs_len;
|
||||||
|
} amduat_asl_collection_snapshot_payload_t;
|
||||||
|
|
||||||
bool amduat_asl_collection_store_init(
|
bool amduat_asl_collection_store_init(
|
||||||
amduat_asl_collection_store_t *collection_store,
|
amduat_asl_collection_store_t *collection_store,
|
||||||
const char *root_path,
|
const char *root_path,
|
||||||
|
|
@ -61,6 +67,13 @@ amduat_asl_collection_error_t amduat_asl_collection_read(
|
||||||
void amduat_asl_collection_refs_free(amduat_reference_t *refs,
|
void amduat_asl_collection_refs_free(amduat_reference_t *refs,
|
||||||
size_t refs_len);
|
size_t refs_len);
|
||||||
|
|
||||||
|
bool amduat_asl_collection_snapshot_payload_decode_v1(
|
||||||
|
amduat_octets_t payload,
|
||||||
|
amduat_asl_collection_snapshot_payload_t *out_snapshot);
|
||||||
|
|
||||||
|
void amduat_asl_collection_snapshot_payload_free(
|
||||||
|
amduat_asl_collection_snapshot_payload_t *snapshot);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
74
include/amduat/asl/collection_view.h
Normal file
74
include/amduat/asl/collection_view.h
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
#ifndef AMDUAT_ASL_COLLECTION_VIEW_H
|
||||||
|
#define AMDUAT_ASL_COLLECTION_VIEW_H
|
||||||
|
|
||||||
|
#include "amduat/asl/core.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum { TYPE_TAG_ASL_COLLECTION_VIEW_1 = 0x00000403u };
|
||||||
|
enum { AMDUAT_TYPE_TAG_ASL_COLLECTION_VIEW_1 = TYPE_TAG_ASL_COLLECTION_VIEW_1 };
|
||||||
|
enum { TYPE_TAG_ASL_SNAPSHOT_INFO_1 = 0x00000405u };
|
||||||
|
enum { AMDUAT_TYPE_TAG_ASL_SNAPSHOT_INFO_1 = TYPE_TAG_ASL_SNAPSHOT_INFO_1 };
|
||||||
|
enum { TYPE_TAG_ASL_LOG_RANGE_1 = 0x00000406u };
|
||||||
|
enum { AMDUAT_TYPE_TAG_ASL_LOG_RANGE_1 = TYPE_TAG_ASL_LOG_RANGE_1 };
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t snapshot_at_offset;
|
||||||
|
amduat_reference_t *refs;
|
||||||
|
size_t refs_len;
|
||||||
|
} amduat_asl_collection_snapshot_info_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t start_offset;
|
||||||
|
uint64_t next_offset;
|
||||||
|
amduat_reference_t *refs;
|
||||||
|
size_t refs_len;
|
||||||
|
} amduat_asl_log_range_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t computed_from_offset;
|
||||||
|
uint64_t computed_up_to_offset;
|
||||||
|
amduat_reference_t *refs;
|
||||||
|
size_t refs_len;
|
||||||
|
} amduat_asl_collection_view_t;
|
||||||
|
|
||||||
|
bool amduat_asl_collection_snapshot_info_encode_v1(
|
||||||
|
const amduat_asl_collection_snapshot_info_t *info,
|
||||||
|
amduat_octets_t *out_bytes);
|
||||||
|
|
||||||
|
bool amduat_asl_collection_snapshot_info_decode_v1(
|
||||||
|
amduat_octets_t bytes,
|
||||||
|
amduat_asl_collection_snapshot_info_t *out_info);
|
||||||
|
|
||||||
|
void amduat_asl_collection_snapshot_info_free(
|
||||||
|
amduat_asl_collection_snapshot_info_t *info);
|
||||||
|
|
||||||
|
bool amduat_asl_log_range_encode_v1(const amduat_asl_log_range_t *range,
|
||||||
|
amduat_octets_t *out_bytes);
|
||||||
|
|
||||||
|
bool amduat_asl_log_range_decode_v1(amduat_octets_t bytes,
|
||||||
|
amduat_asl_log_range_t *out_range);
|
||||||
|
|
||||||
|
void amduat_asl_log_range_free(amduat_asl_log_range_t *range);
|
||||||
|
|
||||||
|
bool amduat_asl_collection_view_encode_v1(
|
||||||
|
const amduat_asl_collection_view_t *view,
|
||||||
|
amduat_octets_t *out_bytes);
|
||||||
|
|
||||||
|
bool amduat_asl_collection_view_decode_v1(
|
||||||
|
amduat_octets_t bytes,
|
||||||
|
amduat_asl_collection_view_t *out_view);
|
||||||
|
|
||||||
|
void amduat_asl_collection_view_free(amduat_asl_collection_view_t *view);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* AMDUAT_ASL_COLLECTION_VIEW_H */
|
||||||
|
|
@ -25,6 +25,16 @@ typedef struct {
|
||||||
amduat_octets_t actor;
|
amduat_octets_t actor;
|
||||||
} amduat_asl_log_entry_t;
|
} amduat_asl_log_entry_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool has_prev;
|
||||||
|
amduat_reference_t prev_ref;
|
||||||
|
uint64_t base_offset;
|
||||||
|
uint32_t entry_count;
|
||||||
|
bool has_timestamp;
|
||||||
|
bool has_actor;
|
||||||
|
amduat_asl_log_entry_t *entries;
|
||||||
|
} amduat_asl_log_chunk_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
amduat_asl_store_t *store;
|
amduat_asl_store_t *store;
|
||||||
amduat_asl_pointer_store_t pointer_store;
|
amduat_asl_pointer_store_t pointer_store;
|
||||||
|
|
@ -55,6 +65,12 @@ amduat_asl_store_error_t amduat_asl_log_read(
|
||||||
void amduat_asl_log_entries_free(amduat_asl_log_entry_t *entries,
|
void amduat_asl_log_entries_free(amduat_asl_log_entry_t *entries,
|
||||||
size_t entries_len);
|
size_t entries_len);
|
||||||
|
|
||||||
|
amduat_asl_store_error_t amduat_asl_log_chunk_decode_v1(
|
||||||
|
amduat_octets_t bytes,
|
||||||
|
amduat_asl_log_chunk_t *out_chunk);
|
||||||
|
|
||||||
|
void amduat_asl_log_chunk_free(amduat_asl_log_chunk_t *chunk);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
27
include/amduat/asl/none.h
Normal file
27
include/amduat/asl/none.h
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef AMDUAT_ASL_NONE_H
|
||||||
|
#define AMDUAT_ASL_NONE_H
|
||||||
|
|
||||||
|
#include "amduat/asl/core.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum { TYPE_TAG_ASL_NONE_1 = 0x00000404u };
|
||||||
|
enum { AMDUAT_TYPE_TAG_ASL_NONE_1 = TYPE_TAG_ASL_NONE_1 };
|
||||||
|
|
||||||
|
bool amduat_asl_none_encode_v1(amduat_octets_t *out_bytes);
|
||||||
|
|
||||||
|
bool amduat_asl_none_decode_v1(amduat_octets_t bytes);
|
||||||
|
|
||||||
|
bool amduat_asl_none_is_artifact(const amduat_artifact_t *artifact);
|
||||||
|
|
||||||
|
bool amduat_asl_none_artifact(amduat_artifact_t *out_artifact);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* AMDUAT_ASL_NONE_H */
|
||||||
|
|
@ -17,6 +17,11 @@ extern "C" {
|
||||||
#define AMDUAT_PEL_KERNEL_OP_HASH_ASL1_NAME "pel.bytes.hash.asl1"
|
#define AMDUAT_PEL_KERNEL_OP_HASH_ASL1_NAME "pel.bytes.hash.asl1"
|
||||||
#define AMDUAT_PEL_KERNEL_OP_PARAMS_NAME "pel.bytes.params"
|
#define AMDUAT_PEL_KERNEL_OP_PARAMS_NAME "pel.bytes.params"
|
||||||
#define AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE_NAME "pel.format.encode"
|
#define AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE_NAME "pel.format.encode"
|
||||||
|
#define AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE_NAME \
|
||||||
|
"collection.snapshot_decode_v1"
|
||||||
|
#define AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE_NAME "log.read_range_v1"
|
||||||
|
#define AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS_NAME \
|
||||||
|
"collection.merge_refs_v1"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
AMDUAT_PEL_KERNEL_OP_CODE_CONCAT = 0x0001u,
|
AMDUAT_PEL_KERNEL_OP_CODE_CONCAT = 0x0001u,
|
||||||
|
|
@ -24,7 +29,10 @@ enum {
|
||||||
AMDUAT_PEL_KERNEL_OP_CODE_CONST = 0x0003u,
|
AMDUAT_PEL_KERNEL_OP_CODE_CONST = 0x0003u,
|
||||||
AMDUAT_PEL_KERNEL_OP_CODE_HASH_ASL1 = 0x0004u,
|
AMDUAT_PEL_KERNEL_OP_CODE_HASH_ASL1 = 0x0004u,
|
||||||
AMDUAT_PEL_KERNEL_OP_CODE_PARAMS = 0x0005u,
|
AMDUAT_PEL_KERNEL_OP_CODE_PARAMS = 0x0005u,
|
||||||
AMDUAT_PEL_KERNEL_OP_CODE_FORMAT_ENCODE = 0x0006u
|
AMDUAT_PEL_KERNEL_OP_CODE_FORMAT_ENCODE = 0x0006u,
|
||||||
|
AMDUAT_PEL_KERNEL_OP_CODE_COLLECTION_SNAPSHOT_DECODE = 0x0007u,
|
||||||
|
AMDUAT_PEL_KERNEL_OP_CODE_LOG_READ_RANGE = 0x0008u,
|
||||||
|
AMDUAT_PEL_KERNEL_OP_CODE_COLLECTION_MERGE_REFS = 0x0009u
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
@ -35,7 +43,13 @@ enum {
|
||||||
AMDUAT_PEL_KERNEL_STATUS_FORMAT_SCHEMA_INVALID = 0x00030001u,
|
AMDUAT_PEL_KERNEL_STATUS_FORMAT_SCHEMA_INVALID = 0x00030001u,
|
||||||
AMDUAT_PEL_KERNEL_STATUS_FORMAT_REGISTRY_INVALID = 0x00030002u,
|
AMDUAT_PEL_KERNEL_STATUS_FORMAT_REGISTRY_INVALID = 0x00030002u,
|
||||||
AMDUAT_PEL_KERNEL_STATUS_FORMAT_MISSING_FIELD = 0x00030003u,
|
AMDUAT_PEL_KERNEL_STATUS_FORMAT_MISSING_FIELD = 0x00030003u,
|
||||||
AMDUAT_PEL_KERNEL_STATUS_FORMAT_TYPE_UNSUPPORTED = 0x00030004u
|
AMDUAT_PEL_KERNEL_STATUS_FORMAT_TYPE_UNSUPPORTED = 0x00030004u,
|
||||||
|
AMDUAT_PEL_KERNEL_STATUS_PARAMS_INVALID = 0x00040001u,
|
||||||
|
AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID = 0x00040002u,
|
||||||
|
AMDUAT_PEL_KERNEL_STATUS_LOG_CHUNK_INVALID = 0x00040003u,
|
||||||
|
AMDUAT_PEL_KERNEL_STATUS_LOG_RANGE_INVALID = 0x00040004u,
|
||||||
|
AMDUAT_PEL_KERNEL_STATUS_COLLECTION_VIEW_INVALID = 0x00040005u,
|
||||||
|
AMDUAT_PEL_KERNEL_STATUS_REF_RESOLVE_FAILED = 0x00040006u
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
@ -44,7 +58,10 @@ typedef enum {
|
||||||
AMDUAT_PEL_KERNEL_OP_CONST = 3,
|
AMDUAT_PEL_KERNEL_OP_CONST = 3,
|
||||||
AMDUAT_PEL_KERNEL_OP_HASH_ASL1 = 4,
|
AMDUAT_PEL_KERNEL_OP_HASH_ASL1 = 4,
|
||||||
AMDUAT_PEL_KERNEL_OP_PARAMS = 5,
|
AMDUAT_PEL_KERNEL_OP_PARAMS = 5,
|
||||||
AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE = 6
|
AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE = 6,
|
||||||
|
AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE = 7,
|
||||||
|
AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE = 8,
|
||||||
|
AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS = 9
|
||||||
} amduat_pel_kernel_op_kind_t;
|
} amduat_pel_kernel_op_kind_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -58,6 +75,11 @@ typedef struct {
|
||||||
struct amduat_pel_kernel_params;
|
struct amduat_pel_kernel_params;
|
||||||
typedef struct amduat_pel_kernel_params amduat_pel_kernel_params_t;
|
typedef struct amduat_pel_kernel_params amduat_pel_kernel_params_t;
|
||||||
|
|
||||||
|
typedef bool (*amduat_pel_kernel_artifact_resolver_t)(
|
||||||
|
amduat_reference_t ref,
|
||||||
|
amduat_artifact_t *out_artifact,
|
||||||
|
void *ctx);
|
||||||
|
|
||||||
const amduat_pel_kernel_op_desc_t *amduat_pel_kernel_op_lookup(
|
const amduat_pel_kernel_op_desc_t *amduat_pel_kernel_op_lookup(
|
||||||
amduat_octets_t name,
|
amduat_octets_t name,
|
||||||
uint32_t version);
|
uint32_t version);
|
||||||
|
|
@ -67,6 +89,15 @@ const amduat_pel_kernel_op_desc_t *amduat_pel_kernel_op_descs(
|
||||||
|
|
||||||
const char *amduat_pel_kernel_op_name(amduat_pel_kernel_op_kind_t kind);
|
const char *amduat_pel_kernel_op_name(amduat_pel_kernel_op_kind_t kind);
|
||||||
|
|
||||||
|
void amduat_pel_kernel_set_artifact_resolver(
|
||||||
|
amduat_pel_kernel_artifact_resolver_t resolver,
|
||||||
|
void *ctx);
|
||||||
|
|
||||||
|
void amduat_pel_kernel_clear_artifact_resolver(void);
|
||||||
|
|
||||||
|
bool amduat_pel_kernel_resolve_artifact(amduat_reference_t ref,
|
||||||
|
amduat_artifact_t *out_artifact);
|
||||||
|
|
||||||
bool amduat_pel_kernel_op_eval(
|
bool amduat_pel_kernel_op_eval(
|
||||||
const amduat_pel_kernel_op_desc_t *desc,
|
const amduat_pel_kernel_op_desc_t *desc,
|
||||||
const amduat_artifact_t *inputs,
|
const amduat_artifact_t *inputs,
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,40 @@ static void amduat_asl_collection_store_u64_le(uint8_t *out, uint64_t value) {
|
||||||
out[7] = (uint8_t)((value >> 56) & 0xffu);
|
out[7] = (uint8_t)((value >> 56) & 0xffu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool amduat_asl_collection_read_u32_le(const uint8_t *data,
|
||||||
|
size_t len,
|
||||||
|
size_t *offset,
|
||||||
|
uint32_t *out) {
|
||||||
|
if (len - *offset < 4u) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out = (uint32_t)data[*offset] |
|
||||||
|
((uint32_t)data[*offset + 1u] << 8) |
|
||||||
|
((uint32_t)data[*offset + 2u] << 16) |
|
||||||
|
((uint32_t)data[*offset + 3u] << 24);
|
||||||
|
*offset += 4u;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_asl_collection_read_u64_le(const uint8_t *data,
|
||||||
|
size_t len,
|
||||||
|
size_t *offset,
|
||||||
|
uint64_t *out) {
|
||||||
|
if (len - *offset < 8u) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out = (uint64_t)data[*offset] |
|
||||||
|
((uint64_t)data[*offset + 1u] << 8) |
|
||||||
|
((uint64_t)data[*offset + 2u] << 16) |
|
||||||
|
((uint64_t)data[*offset + 3u] << 24) |
|
||||||
|
((uint64_t)data[*offset + 4u] << 32) |
|
||||||
|
((uint64_t)data[*offset + 5u] << 40) |
|
||||||
|
((uint64_t)data[*offset + 6u] << 48) |
|
||||||
|
((uint64_t)data[*offset + 7u] << 56);
|
||||||
|
*offset += 8u;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool amduat_asl_collection_add_size(size_t *acc, size_t add) {
|
static bool amduat_asl_collection_add_size(size_t *acc, size_t add) {
|
||||||
if (*acc > SIZE_MAX - add) {
|
if (*acc > SIZE_MAX - add) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -481,3 +515,93 @@ void amduat_asl_collection_refs_free(amduat_reference_t *refs,
|
||||||
}
|
}
|
||||||
free(refs);
|
free(refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool amduat_asl_collection_snapshot_payload_decode_v1(
|
||||||
|
amduat_octets_t payload,
|
||||||
|
amduat_asl_collection_snapshot_payload_t *out_snapshot) {
|
||||||
|
size_t offset = 0u;
|
||||||
|
uint32_t version = 0u;
|
||||||
|
uint32_t entry_count = 0u;
|
||||||
|
|
||||||
|
if (out_snapshot == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out_snapshot->snapshot_offset = 0u;
|
||||||
|
out_snapshot->refs = NULL;
|
||||||
|
out_snapshot->refs_len = 0u;
|
||||||
|
|
||||||
|
if (payload.len < AMDUAT_ASL_COLLECTION_MAGIC_LEN + 4u + 8u + 4u) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (payload.data == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (memcmp(payload.data, k_amduat_asl_collection_magic,
|
||||||
|
AMDUAT_ASL_COLLECTION_MAGIC_LEN) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
offset += AMDUAT_ASL_COLLECTION_MAGIC_LEN;
|
||||||
|
if (!amduat_asl_collection_read_u32_le(payload.data, payload.len,
|
||||||
|
&offset, &version) ||
|
||||||
|
version != AMDUAT_ASL_COLLECTION_VERSION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_collection_read_u64_le(payload.data, payload.len,
|
||||||
|
&offset,
|
||||||
|
&out_snapshot->snapshot_offset)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_collection_read_u32_le(payload.data, payload.len,
|
||||||
|
&offset, &entry_count)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (entry_count == 0u) {
|
||||||
|
return offset == payload.len;
|
||||||
|
}
|
||||||
|
if (entry_count > SIZE_MAX / sizeof(amduat_reference_t)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out_snapshot->refs =
|
||||||
|
(amduat_reference_t *)calloc(entry_count, sizeof(*out_snapshot->refs));
|
||||||
|
if (out_snapshot->refs == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out_snapshot->refs_len = entry_count;
|
||||||
|
|
||||||
|
for (uint32_t i = 0u; i < entry_count; ++i) {
|
||||||
|
uint32_t ref_len = 0u;
|
||||||
|
amduat_octets_t ref_bytes;
|
||||||
|
if (!amduat_asl_collection_read_u32_le(payload.data, payload.len,
|
||||||
|
&offset, &ref_len)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (payload.len - offset < ref_len) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
ref_bytes = amduat_octets(payload.data + offset, ref_len);
|
||||||
|
if (!amduat_enc_asl1_core_decode_reference_v1(
|
||||||
|
ref_bytes, &out_snapshot->refs[i])) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
offset += ref_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset == payload.len;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
amduat_asl_collection_snapshot_payload_free(out_snapshot);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amduat_asl_collection_snapshot_payload_free(
|
||||||
|
amduat_asl_collection_snapshot_payload_t *snapshot) {
|
||||||
|
if (snapshot == NULL || snapshot->refs == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0u; i < snapshot->refs_len; ++i) {
|
||||||
|
amduat_reference_free(&snapshot->refs[i]);
|
||||||
|
}
|
||||||
|
free(snapshot->refs);
|
||||||
|
snapshot->refs = NULL;
|
||||||
|
snapshot->refs_len = 0u;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,16 +25,6 @@ enum {
|
||||||
AMDUAT_ASL_LOG_FLAG_HAS_ACTOR = 1u << 2
|
AMDUAT_ASL_LOG_FLAG_HAS_ACTOR = 1u << 2
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
bool has_prev;
|
|
||||||
amduat_reference_t prev_ref;
|
|
||||||
uint64_t base_offset;
|
|
||||||
uint32_t entry_count;
|
|
||||||
bool has_timestamp;
|
|
||||||
bool has_actor;
|
|
||||||
amduat_asl_log_entry_t *entries;
|
|
||||||
} amduat_asl_log_chunk_t;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
@ -115,7 +105,7 @@ static bool amduat_asl_log_add_size(size_t *acc, size_t add) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void amduat_asl_log_chunk_free(amduat_asl_log_chunk_t *chunk) {
|
void amduat_asl_log_chunk_free(amduat_asl_log_chunk_t *chunk) {
|
||||||
if (chunk == NULL) {
|
if (chunk == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -342,7 +332,7 @@ cleanup:
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static amduat_asl_store_error_t amduat_asl_log_decode_chunk(
|
amduat_asl_store_error_t amduat_asl_log_chunk_decode_v1(
|
||||||
amduat_octets_t bytes,
|
amduat_octets_t bytes,
|
||||||
amduat_asl_log_chunk_t *out_chunk) {
|
amduat_asl_log_chunk_t *out_chunk) {
|
||||||
amduat_asl_log_cursor_t cur;
|
amduat_asl_log_cursor_t cur;
|
||||||
|
|
@ -574,7 +564,8 @@ amduat_asl_store_error_t amduat_asl_log_append(
|
||||||
free(pointer_name);
|
free(pointer_name);
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
}
|
}
|
||||||
store_err = amduat_asl_log_decode_chunk(head_artifact.bytes, &head_chunk);
|
store_err = amduat_asl_log_chunk_decode_v1(head_artifact.bytes,
|
||||||
|
&head_chunk);
|
||||||
amduat_artifact_free(&head_artifact);
|
amduat_artifact_free(&head_artifact);
|
||||||
if (store_err != AMDUAT_ASL_STORE_OK) {
|
if (store_err != AMDUAT_ASL_STORE_OK) {
|
||||||
amduat_reference_free(&head_ref);
|
amduat_reference_free(&head_ref);
|
||||||
|
|
@ -744,7 +735,7 @@ amduat_asl_store_error_t amduat_asl_log_read(
|
||||||
amduat_reference_free(&head_ref);
|
amduat_reference_free(&head_ref);
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
}
|
}
|
||||||
err = amduat_asl_log_decode_chunk(artifact.bytes, &chunk);
|
err = amduat_asl_log_chunk_decode_v1(artifact.bytes, &chunk);
|
||||||
amduat_artifact_free(&artifact);
|
amduat_artifact_free(&artifact);
|
||||||
if (err != AMDUAT_ASL_STORE_OK) {
|
if (err != AMDUAT_ASL_STORE_OK) {
|
||||||
if (current_ref_owned) {
|
if (current_ref_owned) {
|
||||||
|
|
|
||||||
520
src/near_core/asl/collection_view.c
Normal file
520
src/near_core/asl/collection_view.c
Normal file
|
|
@ -0,0 +1,520 @@
|
||||||
|
#include "amduat/asl/collection_view.h"
|
||||||
|
|
||||||
|
#include "amduat/enc/asl1_core_codec.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN = 8,
|
||||||
|
AMDUAT_ASL_COLLECTION_VIEW_VERSION = 1,
|
||||||
|
AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN = 8,
|
||||||
|
AMDUAT_ASL_SNAPSHOT_INFO_VERSION = 1,
|
||||||
|
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN = 8,
|
||||||
|
AMDUAT_ASL_LOG_RANGE_VERSION = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t k_amduat_asl_collection_view_magic[
|
||||||
|
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN] = {
|
||||||
|
'A', 'S', 'L', 'C', 'V', 'W', '1', '\0'
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t k_amduat_asl_snapshot_info_magic[
|
||||||
|
AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN] = {
|
||||||
|
'A', 'S', 'L', 'S', 'N', 'P', '1', '\0'
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t k_amduat_asl_log_range_magic[
|
||||||
|
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN] = {
|
||||||
|
'A', 'S', 'L', 'R', 'N', 'G', '1', '\0'
|
||||||
|
};
|
||||||
|
|
||||||
|
static void amduat_asl_store_u32_le(uint8_t *out, uint32_t value) {
|
||||||
|
out[0] = (uint8_t)(value & 0xffu);
|
||||||
|
out[1] = (uint8_t)((value >> 8) & 0xffu);
|
||||||
|
out[2] = (uint8_t)((value >> 16) & 0xffu);
|
||||||
|
out[3] = (uint8_t)((value >> 24) & 0xffu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amduat_asl_store_u64_le(uint8_t *out, uint64_t value) {
|
||||||
|
out[0] = (uint8_t)(value & 0xffu);
|
||||||
|
out[1] = (uint8_t)((value >> 8) & 0xffu);
|
||||||
|
out[2] = (uint8_t)((value >> 16) & 0xffu);
|
||||||
|
out[3] = (uint8_t)((value >> 24) & 0xffu);
|
||||||
|
out[4] = (uint8_t)((value >> 32) & 0xffu);
|
||||||
|
out[5] = (uint8_t)((value >> 40) & 0xffu);
|
||||||
|
out[6] = (uint8_t)((value >> 48) & 0xffu);
|
||||||
|
out[7] = (uint8_t)((value >> 56) & 0xffu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_asl_read_u32_le(const uint8_t *data,
|
||||||
|
size_t len,
|
||||||
|
size_t *offset,
|
||||||
|
uint32_t *out) {
|
||||||
|
if (len - *offset < 4u) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out = (uint32_t)data[*offset] |
|
||||||
|
((uint32_t)data[*offset + 1u] << 8) |
|
||||||
|
((uint32_t)data[*offset + 2u] << 16) |
|
||||||
|
((uint32_t)data[*offset + 3u] << 24);
|
||||||
|
*offset += 4u;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_asl_read_u64_le(const uint8_t *data,
|
||||||
|
size_t len,
|
||||||
|
size_t *offset,
|
||||||
|
uint64_t *out) {
|
||||||
|
if (len - *offset < 8u) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out = (uint64_t)data[*offset] |
|
||||||
|
((uint64_t)data[*offset + 1u] << 8) |
|
||||||
|
((uint64_t)data[*offset + 2u] << 16) |
|
||||||
|
((uint64_t)data[*offset + 3u] << 24) |
|
||||||
|
((uint64_t)data[*offset + 4u] << 32) |
|
||||||
|
((uint64_t)data[*offset + 5u] << 40) |
|
||||||
|
((uint64_t)data[*offset + 6u] << 48) |
|
||||||
|
((uint64_t)data[*offset + 7u] << 56);
|
||||||
|
*offset += 8u;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_asl_add_size(size_t *acc, size_t add) {
|
||||||
|
if (*acc > SIZE_MAX - add) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*acc += add;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_asl_encode_refs(const amduat_reference_t *refs,
|
||||||
|
size_t refs_len,
|
||||||
|
size_t *out_total_len) {
|
||||||
|
size_t total = 0u;
|
||||||
|
|
||||||
|
if (refs_len > UINT32_MAX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (size_t i = 0u; i < refs_len; ++i) {
|
||||||
|
amduat_octets_t ref_bytes = amduat_octets(NULL, 0u);
|
||||||
|
if (!amduat_enc_asl1_core_encode_reference_v1(refs[i], &ref_bytes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_add_size(&total, 4u + ref_bytes.len)) {
|
||||||
|
free((void *)ref_bytes.data);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
free((void *)ref_bytes.data);
|
||||||
|
}
|
||||||
|
*out_total_len = total;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_asl_write_refs(uint8_t *buffer,
|
||||||
|
size_t total_len,
|
||||||
|
size_t *offset,
|
||||||
|
const amduat_reference_t *refs,
|
||||||
|
size_t refs_len) {
|
||||||
|
for (size_t i = 0u; i < refs_len; ++i) {
|
||||||
|
amduat_octets_t ref_bytes = amduat_octets(NULL, 0u);
|
||||||
|
if (!amduat_enc_asl1_core_encode_reference_v1(refs[i], &ref_bytes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (total_len - *offset < 4u + ref_bytes.len) {
|
||||||
|
free((void *)ref_bytes.data);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
amduat_asl_store_u32_le(buffer + *offset, (uint32_t)ref_bytes.len);
|
||||||
|
*offset += 4u;
|
||||||
|
memcpy(buffer + *offset, ref_bytes.data, ref_bytes.len);
|
||||||
|
*offset += ref_bytes.len;
|
||||||
|
free((void *)ref_bytes.data);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_asl_decode_refs(amduat_octets_t bytes,
|
||||||
|
size_t *offset,
|
||||||
|
uint32_t refs_len,
|
||||||
|
amduat_reference_t **out_refs,
|
||||||
|
size_t *out_refs_len) {
|
||||||
|
amduat_reference_t *refs = NULL;
|
||||||
|
|
||||||
|
if (out_refs == NULL || out_refs_len == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out_refs = NULL;
|
||||||
|
*out_refs_len = 0u;
|
||||||
|
|
||||||
|
if (refs_len == 0u) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (refs_len > SIZE_MAX / sizeof(*refs)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
refs = (amduat_reference_t *)calloc(refs_len, sizeof(*refs));
|
||||||
|
if (refs == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0u; i < refs_len; ++i) {
|
||||||
|
uint32_t ref_len = 0u;
|
||||||
|
amduat_octets_t ref_bytes;
|
||||||
|
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, offset, &ref_len)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (bytes.len - *offset < ref_len) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
ref_bytes = amduat_octets(bytes.data + *offset, ref_len);
|
||||||
|
if (!amduat_enc_asl1_core_decode_reference_v1(ref_bytes, &refs[i])) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
*offset += ref_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_refs = refs;
|
||||||
|
*out_refs_len = refs_len;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
for (uint32_t i = 0u; i < refs_len; ++i) {
|
||||||
|
amduat_reference_free(&refs[i]);
|
||||||
|
}
|
||||||
|
free(refs);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_asl_collection_snapshot_info_encode_v1(
|
||||||
|
const amduat_asl_collection_snapshot_info_t *info,
|
||||||
|
amduat_octets_t *out_bytes) {
|
||||||
|
uint8_t *buffer;
|
||||||
|
size_t total_len = 0u;
|
||||||
|
size_t refs_len_bytes = 0u;
|
||||||
|
size_t offset = 0u;
|
||||||
|
|
||||||
|
if (out_bytes == NULL || info == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out_bytes->data = NULL;
|
||||||
|
out_bytes->len = 0u;
|
||||||
|
|
||||||
|
if (!amduat_asl_add_size(&total_len,
|
||||||
|
AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN + 4u + 8u + 4u)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_encode_refs(info->refs, info->refs_len, &refs_len_bytes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_add_size(&total_len, refs_len_bytes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = (uint8_t *)malloc(total_len);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer + offset, k_amduat_asl_snapshot_info_magic,
|
||||||
|
AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN);
|
||||||
|
offset += AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN;
|
||||||
|
amduat_asl_store_u32_le(buffer + offset, AMDUAT_ASL_SNAPSHOT_INFO_VERSION);
|
||||||
|
offset += 4u;
|
||||||
|
amduat_asl_store_u64_le(buffer + offset, info->snapshot_at_offset);
|
||||||
|
offset += 8u;
|
||||||
|
amduat_asl_store_u32_le(buffer + offset, (uint32_t)info->refs_len);
|
||||||
|
offset += 4u;
|
||||||
|
if (!amduat_asl_write_refs(buffer, total_len, &offset,
|
||||||
|
info->refs, info->refs_len)) {
|
||||||
|
free(buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset != total_len) {
|
||||||
|
free(buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out_bytes = amduat_octets(buffer, total_len);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_asl_collection_snapshot_info_decode_v1(
|
||||||
|
amduat_octets_t bytes,
|
||||||
|
amduat_asl_collection_snapshot_info_t *out_info) {
|
||||||
|
size_t offset = 0u;
|
||||||
|
uint32_t version = 0u;
|
||||||
|
uint32_t refs_len = 0u;
|
||||||
|
|
||||||
|
if (out_info == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out_info->snapshot_at_offset = 0u;
|
||||||
|
out_info->refs = NULL;
|
||||||
|
out_info->refs_len = 0u;
|
||||||
|
|
||||||
|
if (bytes.len < AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN + 4u + 8u + 4u ||
|
||||||
|
bytes.data == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (memcmp(bytes.data, k_amduat_asl_snapshot_info_magic,
|
||||||
|
AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
offset += AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN;
|
||||||
|
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &version) ||
|
||||||
|
version != AMDUAT_ASL_SNAPSHOT_INFO_VERSION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_read_u64_le(bytes.data, bytes.len, &offset,
|
||||||
|
&out_info->snapshot_at_offset)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &refs_len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_decode_refs(bytes, &offset, refs_len,
|
||||||
|
&out_info->refs, &out_info->refs_len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return offset == bytes.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amduat_asl_collection_snapshot_info_free(
|
||||||
|
amduat_asl_collection_snapshot_info_t *info) {
|
||||||
|
if (info == NULL || info->refs == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0u; i < info->refs_len; ++i) {
|
||||||
|
amduat_reference_free(&info->refs[i]);
|
||||||
|
}
|
||||||
|
free(info->refs);
|
||||||
|
info->refs = NULL;
|
||||||
|
info->refs_len = 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_asl_log_range_encode_v1(const amduat_asl_log_range_t *range,
|
||||||
|
amduat_octets_t *out_bytes) {
|
||||||
|
uint8_t *buffer;
|
||||||
|
size_t total_len = 0u;
|
||||||
|
size_t refs_len_bytes = 0u;
|
||||||
|
size_t offset = 0u;
|
||||||
|
|
||||||
|
if (out_bytes == NULL || range == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out_bytes->data = NULL;
|
||||||
|
out_bytes->len = 0u;
|
||||||
|
|
||||||
|
if (!amduat_asl_add_size(&total_len,
|
||||||
|
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN + 4u + 8u + 8u + 4u)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_encode_refs(range->refs, range->refs_len, &refs_len_bytes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_add_size(&total_len, refs_len_bytes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = (uint8_t *)malloc(total_len);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer + offset, k_amduat_asl_log_range_magic,
|
||||||
|
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN);
|
||||||
|
offset += AMDUAT_ASL_LOG_RANGE_MAGIC_LEN;
|
||||||
|
amduat_asl_store_u32_le(buffer + offset, AMDUAT_ASL_LOG_RANGE_VERSION);
|
||||||
|
offset += 4u;
|
||||||
|
amduat_asl_store_u64_le(buffer + offset, range->start_offset);
|
||||||
|
offset += 8u;
|
||||||
|
amduat_asl_store_u64_le(buffer + offset, range->next_offset);
|
||||||
|
offset += 8u;
|
||||||
|
amduat_asl_store_u32_le(buffer + offset, (uint32_t)range->refs_len);
|
||||||
|
offset += 4u;
|
||||||
|
if (!amduat_asl_write_refs(buffer, total_len, &offset,
|
||||||
|
range->refs, range->refs_len)) {
|
||||||
|
free(buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset != total_len) {
|
||||||
|
free(buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out_bytes = amduat_octets(buffer, total_len);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_asl_log_range_decode_v1(amduat_octets_t bytes,
|
||||||
|
amduat_asl_log_range_t *out_range) {
|
||||||
|
size_t offset = 0u;
|
||||||
|
uint32_t version = 0u;
|
||||||
|
uint32_t refs_len = 0u;
|
||||||
|
|
||||||
|
if (out_range == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out_range->start_offset = 0u;
|
||||||
|
out_range->next_offset = 0u;
|
||||||
|
out_range->refs = NULL;
|
||||||
|
out_range->refs_len = 0u;
|
||||||
|
|
||||||
|
if (bytes.len <
|
||||||
|
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN + 4u + 8u + 8u + 4u ||
|
||||||
|
bytes.data == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (memcmp(bytes.data, k_amduat_asl_log_range_magic,
|
||||||
|
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
offset += AMDUAT_ASL_LOG_RANGE_MAGIC_LEN;
|
||||||
|
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &version) ||
|
||||||
|
version != AMDUAT_ASL_LOG_RANGE_VERSION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_read_u64_le(bytes.data, bytes.len, &offset,
|
||||||
|
&out_range->start_offset) ||
|
||||||
|
!amduat_asl_read_u64_le(bytes.data, bytes.len, &offset,
|
||||||
|
&out_range->next_offset)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &refs_len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_decode_refs(bytes, &offset, refs_len,
|
||||||
|
&out_range->refs, &out_range->refs_len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return offset == bytes.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amduat_asl_log_range_free(amduat_asl_log_range_t *range) {
|
||||||
|
if (range == NULL || range->refs == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0u; i < range->refs_len; ++i) {
|
||||||
|
amduat_reference_free(&range->refs[i]);
|
||||||
|
}
|
||||||
|
free(range->refs);
|
||||||
|
range->refs = NULL;
|
||||||
|
range->refs_len = 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_asl_collection_view_encode_v1(
|
||||||
|
const amduat_asl_collection_view_t *view,
|
||||||
|
amduat_octets_t *out_bytes) {
|
||||||
|
uint8_t *buffer;
|
||||||
|
size_t total_len = 0u;
|
||||||
|
size_t refs_len_bytes = 0u;
|
||||||
|
size_t offset = 0u;
|
||||||
|
|
||||||
|
if (out_bytes == NULL || view == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out_bytes->data = NULL;
|
||||||
|
out_bytes->len = 0u;
|
||||||
|
|
||||||
|
if (!amduat_asl_add_size(&total_len,
|
||||||
|
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN + 4u +
|
||||||
|
8u + 8u + 4u)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_encode_refs(view->refs, view->refs_len, &refs_len_bytes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_add_size(&total_len, refs_len_bytes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = (uint8_t *)malloc(total_len);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer + offset, k_amduat_asl_collection_view_magic,
|
||||||
|
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN);
|
||||||
|
offset += AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN;
|
||||||
|
amduat_asl_store_u32_le(buffer + offset,
|
||||||
|
AMDUAT_ASL_COLLECTION_VIEW_VERSION);
|
||||||
|
offset += 4u;
|
||||||
|
amduat_asl_store_u64_le(buffer + offset, view->computed_from_offset);
|
||||||
|
offset += 8u;
|
||||||
|
amduat_asl_store_u64_le(buffer + offset, view->computed_up_to_offset);
|
||||||
|
offset += 8u;
|
||||||
|
amduat_asl_store_u32_le(buffer + offset, (uint32_t)view->refs_len);
|
||||||
|
offset += 4u;
|
||||||
|
if (!amduat_asl_write_refs(buffer, total_len, &offset,
|
||||||
|
view->refs, view->refs_len)) {
|
||||||
|
free(buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset != total_len) {
|
||||||
|
free(buffer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out_bytes = amduat_octets(buffer, total_len);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_asl_collection_view_decode_v1(
|
||||||
|
amduat_octets_t bytes,
|
||||||
|
amduat_asl_collection_view_t *out_view) {
|
||||||
|
size_t offset = 0u;
|
||||||
|
uint32_t version = 0u;
|
||||||
|
uint32_t refs_len = 0u;
|
||||||
|
|
||||||
|
if (out_view == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out_view->computed_from_offset = 0u;
|
||||||
|
out_view->computed_up_to_offset = 0u;
|
||||||
|
out_view->refs = NULL;
|
||||||
|
out_view->refs_len = 0u;
|
||||||
|
|
||||||
|
if (bytes.len <
|
||||||
|
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN + 4u + 8u + 8u + 4u ||
|
||||||
|
bytes.data == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (memcmp(bytes.data, k_amduat_asl_collection_view_magic,
|
||||||
|
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
offset += AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN;
|
||||||
|
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &version) ||
|
||||||
|
version != AMDUAT_ASL_COLLECTION_VIEW_VERSION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_read_u64_le(bytes.data, bytes.len, &offset,
|
||||||
|
&out_view->computed_from_offset) ||
|
||||||
|
!amduat_asl_read_u64_le(bytes.data, bytes.len, &offset,
|
||||||
|
&out_view->computed_up_to_offset)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &refs_len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_decode_refs(bytes, &offset, refs_len,
|
||||||
|
&out_view->refs, &out_view->refs_len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return offset == bytes.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amduat_asl_collection_view_free(amduat_asl_collection_view_t *view) {
|
||||||
|
if (view == NULL || view->refs == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0u; i < view->refs_len; ++i) {
|
||||||
|
amduat_reference_free(&view->refs[i]);
|
||||||
|
}
|
||||||
|
free(view->refs);
|
||||||
|
view->refs = NULL;
|
||||||
|
view->refs_len = 0u;
|
||||||
|
}
|
||||||
110
src/near_core/asl/none.c
Normal file
110
src/near_core/asl/none.c
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
#include "amduat/asl/none.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
AMDUAT_ASL_NONE_MAGIC_LEN = 8,
|
||||||
|
AMDUAT_ASL_NONE_VERSION = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t k_amduat_asl_none_magic[AMDUAT_ASL_NONE_MAGIC_LEN] = {
|
||||||
|
'A', 'S', 'L', 'N', 'O', 'N', '1', '\0'
|
||||||
|
};
|
||||||
|
|
||||||
|
static void amduat_asl_none_store_u32_le(uint8_t *out, uint32_t value) {
|
||||||
|
out[0] = (uint8_t)(value & 0xffu);
|
||||||
|
out[1] = (uint8_t)((value >> 8) & 0xffu);
|
||||||
|
out[2] = (uint8_t)((value >> 16) & 0xffu);
|
||||||
|
out[3] = (uint8_t)((value >> 24) & 0xffu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_asl_none_read_u32_le(const uint8_t *data,
|
||||||
|
size_t len,
|
||||||
|
size_t *offset,
|
||||||
|
uint32_t *out) {
|
||||||
|
if (len - *offset < 4u) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out = (uint32_t)data[*offset] |
|
||||||
|
((uint32_t)data[*offset + 1u] << 8) |
|
||||||
|
((uint32_t)data[*offset + 2u] << 16) |
|
||||||
|
((uint32_t)data[*offset + 3u] << 24);
|
||||||
|
*offset += 4u;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_asl_none_encode_v1(amduat_octets_t *out_bytes) {
|
||||||
|
uint8_t *buffer;
|
||||||
|
size_t offset = 0u;
|
||||||
|
|
||||||
|
if (out_bytes == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out_bytes->data = NULL;
|
||||||
|
out_bytes->len = 0u;
|
||||||
|
|
||||||
|
buffer = (uint8_t *)malloc(AMDUAT_ASL_NONE_MAGIC_LEN + 4u);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer + offset, k_amduat_asl_none_magic, AMDUAT_ASL_NONE_MAGIC_LEN);
|
||||||
|
offset += AMDUAT_ASL_NONE_MAGIC_LEN;
|
||||||
|
amduat_asl_none_store_u32_le(buffer + offset, AMDUAT_ASL_NONE_VERSION);
|
||||||
|
offset += 4u;
|
||||||
|
|
||||||
|
out_bytes->data = buffer;
|
||||||
|
out_bytes->len = offset;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_asl_none_decode_v1(amduat_octets_t bytes) {
|
||||||
|
size_t offset = 0u;
|
||||||
|
uint32_t version = 0u;
|
||||||
|
|
||||||
|
if (bytes.len != AMDUAT_ASL_NONE_MAGIC_LEN + 4u) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (bytes.data == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (memcmp(bytes.data, k_amduat_asl_none_magic,
|
||||||
|
AMDUAT_ASL_NONE_MAGIC_LEN) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
offset += AMDUAT_ASL_NONE_MAGIC_LEN;
|
||||||
|
if (!amduat_asl_none_read_u32_le(bytes.data, bytes.len, &offset, &version)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (version != AMDUAT_ASL_NONE_VERSION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return offset == bytes.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_asl_none_is_artifact(const amduat_artifact_t *artifact) {
|
||||||
|
if (artifact == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!artifact->has_type_tag ||
|
||||||
|
artifact->type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_NONE_1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return amduat_asl_none_decode_v1(artifact->bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_asl_none_artifact(amduat_artifact_t *out_artifact) {
|
||||||
|
amduat_octets_t bytes = amduat_octets(NULL, 0u);
|
||||||
|
|
||||||
|
if (out_artifact == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_none_encode_v1(&bytes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out_artifact =
|
||||||
|
amduat_artifact_with_type(bytes, amduat_type_tag(AMDUAT_TYPE_TAG_ASL_NONE_1));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
@ -95,6 +95,16 @@ const char *amduat_format_pel_kernel_kind_name(
|
||||||
return "const";
|
return "const";
|
||||||
case AMDUAT_PEL_KERNEL_OP_HASH_ASL1:
|
case AMDUAT_PEL_KERNEL_OP_HASH_ASL1:
|
||||||
return "hash_asl1";
|
return "hash_asl1";
|
||||||
|
case AMDUAT_PEL_KERNEL_OP_PARAMS:
|
||||||
|
return "params";
|
||||||
|
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
|
||||||
|
return "format_encode";
|
||||||
|
case AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE:
|
||||||
|
return "collection_snapshot_decode";
|
||||||
|
case AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE:
|
||||||
|
return "log_read_range";
|
||||||
|
case AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS:
|
||||||
|
return "collection_merge_refs";
|
||||||
default:
|
default:
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "amduat/pel/opreg_kernel.h"
|
#include "amduat/pel/opreg_kernel.h"
|
||||||
#include "amduat/pel/opreg_kernel_params.h"
|
#include "amduat/pel/opreg_kernel_params.h"
|
||||||
|
#include "kernel_collection.h"
|
||||||
#include "amduat/hash/asl1.h"
|
#include "amduat/hash/asl1.h"
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
@ -64,8 +65,32 @@ static const amduat_pel_kernel_op_desc_t k_kernel_descs[] = {
|
||||||
3,
|
3,
|
||||||
1
|
1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE,
|
||||||
|
AMDUAT_PEL_KERNEL_OP_CODE_COLLECTION_SNAPSHOT_DECODE,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE,
|
||||||
|
AMDUAT_PEL_KERNEL_OP_CODE_LOG_READ_RANGE,
|
||||||
|
3,
|
||||||
|
3,
|
||||||
|
1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS,
|
||||||
|
AMDUAT_PEL_KERNEL_OP_CODE_COLLECTION_MERGE_REFS,
|
||||||
|
4,
|
||||||
|
4,
|
||||||
|
1
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static amduat_pel_kernel_artifact_resolver_t g_resolver = NULL;
|
||||||
|
static void *g_resolver_ctx = NULL;
|
||||||
|
|
||||||
const amduat_pel_kernel_op_desc_t *amduat_pel_kernel_op_lookup(
|
const amduat_pel_kernel_op_desc_t *amduat_pel_kernel_op_lookup(
|
||||||
amduat_octets_t name,
|
amduat_octets_t name,
|
||||||
uint32_t version) {
|
uint32_t version) {
|
||||||
|
|
@ -90,6 +115,16 @@ const amduat_pel_kernel_op_desc_t *amduat_pel_kernel_op_lookup(
|
||||||
if (amduat_name_eq(name, AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE_NAME)) {
|
if (amduat_name_eq(name, AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE_NAME)) {
|
||||||
return &k_kernel_descs[5];
|
return &k_kernel_descs[5];
|
||||||
}
|
}
|
||||||
|
if (amduat_name_eq(name,
|
||||||
|
AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE_NAME)) {
|
||||||
|
return &k_kernel_descs[6];
|
||||||
|
}
|
||||||
|
if (amduat_name_eq(name, AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE_NAME)) {
|
||||||
|
return &k_kernel_descs[7];
|
||||||
|
}
|
||||||
|
if (amduat_name_eq(name, AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS_NAME)) {
|
||||||
|
return &k_kernel_descs[8];
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,11 +150,37 @@ const char *amduat_pel_kernel_op_name(amduat_pel_kernel_op_kind_t kind) {
|
||||||
return AMDUAT_PEL_KERNEL_OP_PARAMS_NAME;
|
return AMDUAT_PEL_KERNEL_OP_PARAMS_NAME;
|
||||||
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
|
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
|
||||||
return AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE_NAME;
|
return AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE_NAME;
|
||||||
|
case AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE:
|
||||||
|
return AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE_NAME;
|
||||||
|
case AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE:
|
||||||
|
return AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE_NAME;
|
||||||
|
case AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS:
|
||||||
|
return AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS_NAME;
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void amduat_pel_kernel_set_artifact_resolver(
|
||||||
|
amduat_pel_kernel_artifact_resolver_t resolver,
|
||||||
|
void *ctx) {
|
||||||
|
g_resolver = resolver;
|
||||||
|
g_resolver_ctx = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amduat_pel_kernel_clear_artifact_resolver(void) {
|
||||||
|
g_resolver = NULL;
|
||||||
|
g_resolver_ctx = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_pel_kernel_resolve_artifact(amduat_reference_t ref,
|
||||||
|
amduat_artifact_t *out_artifact) {
|
||||||
|
if (g_resolver == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return g_resolver(ref, out_artifact, g_resolver_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
static bool amduat_type_tags_match(const amduat_artifact_t *a,
|
static bool amduat_type_tags_match(const amduat_artifact_t *a,
|
||||||
const amduat_artifact_t *b) {
|
const amduat_artifact_t *b) {
|
||||||
if (a->has_type_tag != b->has_type_tag) {
|
if (a->has_type_tag != b->has_type_tag) {
|
||||||
|
|
@ -1537,6 +1598,15 @@ bool amduat_pel_kernel_op_eval(
|
||||||
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
|
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
|
||||||
return amduat_kernel_format_encode(inputs, inputs_len, out_outputs,
|
return amduat_kernel_format_encode(inputs, inputs_len, out_outputs,
|
||||||
out_outputs_len, out_status_code);
|
out_outputs_len, out_status_code);
|
||||||
|
case AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE:
|
||||||
|
return amduat_kernel_collection_snapshot_decode(
|
||||||
|
inputs, inputs_len, out_outputs, out_outputs_len, out_status_code);
|
||||||
|
case AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE:
|
||||||
|
return amduat_kernel_log_read_range(
|
||||||
|
inputs, inputs_len, out_outputs, out_outputs_len, out_status_code);
|
||||||
|
case AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS:
|
||||||
|
return amduat_kernel_collection_merge_refs(
|
||||||
|
inputs, inputs_len, out_outputs, out_outputs_len, out_status_code);
|
||||||
default:
|
default:
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_INTERNAL;
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_INTERNAL;
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
615
src/pel_stack/opreg/kernel_collection.c
Normal file
615
src/pel_stack/opreg/kernel_collection.c
Normal file
|
|
@ -0,0 +1,615 @@
|
||||||
|
#include "kernel_collection.h"
|
||||||
|
|
||||||
|
#include "amduat/asl/collection.h"
|
||||||
|
#include "amduat/asl/collection_view.h"
|
||||||
|
#include "amduat/asl/log_store.h"
|
||||||
|
#include "amduat/asl/none.h"
|
||||||
|
#include "amduat/asl/record.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static bool amduat_alloc_outputs(size_t count,
|
||||||
|
amduat_artifact_t **out_outputs) {
|
||||||
|
amduat_artifact_t *outputs;
|
||||||
|
|
||||||
|
if (out_outputs == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
outputs = (amduat_artifact_t *)calloc(count, sizeof(*outputs));
|
||||||
|
if (outputs == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out_outputs = outputs;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_load_u64_le(amduat_octets_t bytes,
|
||||||
|
size_t offset,
|
||||||
|
uint64_t *out) {
|
||||||
|
const uint8_t *data;
|
||||||
|
|
||||||
|
if (out == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (bytes.len - offset < 8u || bytes.data == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
data = bytes.data + offset;
|
||||||
|
*out = (uint64_t)data[0] |
|
||||||
|
((uint64_t)data[1] << 8) |
|
||||||
|
((uint64_t)data[2] << 16) |
|
||||||
|
((uint64_t)data[3] << 24) |
|
||||||
|
((uint64_t)data[4] << 32) |
|
||||||
|
((uint64_t)data[5] << 40) |
|
||||||
|
((uint64_t)data[6] << 48) |
|
||||||
|
((uint64_t)data[7] << 56);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_load_u32_le(amduat_octets_t bytes,
|
||||||
|
size_t offset,
|
||||||
|
uint32_t *out) {
|
||||||
|
const uint8_t *data;
|
||||||
|
|
||||||
|
if (out == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (bytes.len - offset < 4u || bytes.data == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
data = bytes.data + offset;
|
||||||
|
*out = (uint32_t)data[0] |
|
||||||
|
((uint32_t)data[1] << 8) |
|
||||||
|
((uint32_t)data[2] << 16) |
|
||||||
|
((uint32_t)data[3] << 24);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_decode_params(const amduat_artifact_t *artifact,
|
||||||
|
uint64_t *out_from,
|
||||||
|
uint32_t *out_limit) {
|
||||||
|
const char k_params_schema[] = "pel/params";
|
||||||
|
amduat_asl_record_t record;
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
if (artifact == NULL || out_from == NULL || out_limit == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!artifact->has_type_tag ||
|
||||||
|
artifact->type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_RECORD_1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_record_decode_v1(artifact->bytes, &record)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (record.schema.len != strlen(k_params_schema) ||
|
||||||
|
record.schema.data == NULL ||
|
||||||
|
memcmp(record.schema.data, k_params_schema,
|
||||||
|
record.schema.len) != 0) {
|
||||||
|
amduat_asl_record_free(&record);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (record.payload.len != 12u) {
|
||||||
|
amduat_asl_record_free(&record);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_load_u64_le(record.payload, 0u, out_from) ||
|
||||||
|
!amduat_load_u32_le(record.payload, 8u, out_limit)) {
|
||||||
|
amduat_asl_record_free(&record);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ok = true;
|
||||||
|
amduat_asl_record_free(&record);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_log_chunk_from_artifact(
|
||||||
|
const amduat_artifact_t *artifact,
|
||||||
|
amduat_asl_log_chunk_t *out_chunk) {
|
||||||
|
if (artifact == NULL || out_chunk == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!artifact->has_type_tag ||
|
||||||
|
artifact->type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_LOG_CHUNK_1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return amduat_asl_log_chunk_decode_v1(artifact->bytes, out_chunk) ==
|
||||||
|
AMDUAT_ASL_STORE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_kernel_collection_snapshot_decode(
|
||||||
|
const amduat_artifact_t *inputs,
|
||||||
|
size_t inputs_len,
|
||||||
|
amduat_artifact_t **out_outputs,
|
||||||
|
size_t *out_outputs_len,
|
||||||
|
uint32_t *out_status_code) {
|
||||||
|
amduat_asl_collection_snapshot_payload_t snapshot;
|
||||||
|
amduat_asl_collection_snapshot_info_t info;
|
||||||
|
amduat_asl_record_t record;
|
||||||
|
amduat_octets_t encoded = amduat_octets(NULL, 0u);
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
if (inputs == NULL || inputs_len != 1u) {
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_INTERNAL;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&snapshot, 0, sizeof(snapshot));
|
||||||
|
memset(&info, 0, sizeof(info));
|
||||||
|
memset(&record, 0, sizeof(record));
|
||||||
|
|
||||||
|
if (amduat_asl_none_is_artifact(&inputs[0])) {
|
||||||
|
info.snapshot_at_offset = 0u;
|
||||||
|
info.refs = NULL;
|
||||||
|
info.refs_len = 0u;
|
||||||
|
} else {
|
||||||
|
if (!inputs[0].has_type_tag ||
|
||||||
|
inputs[0].type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_RECORD_1) {
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_record_decode_v1(inputs[0].bytes, &record)) {
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (record.schema.len != strlen("collection/snapshot") ||
|
||||||
|
record.schema.data == NULL ||
|
||||||
|
memcmp(record.schema.data, "collection/snapshot",
|
||||||
|
record.schema.len) != 0) {
|
||||||
|
amduat_asl_record_free(&record);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_collection_snapshot_payload_decode_v1(record.payload,
|
||||||
|
&snapshot)) {
|
||||||
|
amduat_asl_record_free(&record);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
info.snapshot_at_offset = snapshot.snapshot_offset;
|
||||||
|
info.refs = snapshot.refs;
|
||||||
|
info.refs_len = snapshot.refs_len;
|
||||||
|
amduat_asl_record_free(&record);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_asl_collection_snapshot_info_encode_v1(&info, &encoded)) {
|
||||||
|
amduat_asl_collection_snapshot_payload_free(&snapshot);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_alloc_outputs(1u, out_outputs)) {
|
||||||
|
amduat_asl_collection_snapshot_payload_free(&snapshot);
|
||||||
|
free((void *)encoded.data);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*out_outputs)[0] = amduat_artifact_with_type(
|
||||||
|
encoded, amduat_type_tag(AMDUAT_TYPE_TAG_ASL_SNAPSHOT_INFO_1));
|
||||||
|
if (out_outputs_len != NULL) {
|
||||||
|
*out_outputs_len = 1u;
|
||||||
|
}
|
||||||
|
ok = true;
|
||||||
|
|
||||||
|
amduat_asl_collection_snapshot_payload_free(&snapshot);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_kernel_log_read_range(
|
||||||
|
const amduat_artifact_t *inputs,
|
||||||
|
size_t inputs_len,
|
||||||
|
amduat_artifact_t **out_outputs,
|
||||||
|
size_t *out_outputs_len,
|
||||||
|
uint32_t *out_status_code) {
|
||||||
|
amduat_asl_log_range_t range;
|
||||||
|
amduat_octets_t encoded = amduat_octets(NULL, 0u);
|
||||||
|
uint64_t from_offset = 0u;
|
||||||
|
uint32_t limit = 0u;
|
||||||
|
uint64_t limit_from_offset = 0u;
|
||||||
|
uint32_t limit_value = 0u;
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
if (inputs == NULL || inputs_len != 3u) {
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_INTERNAL;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_decode_params(&inputs[1], &from_offset, &limit_value)) {
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_PARAMS_INVALID;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_decode_params(&inputs[2], &limit_from_offset, &limit)) {
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_PARAMS_INVALID;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
(void)limit_from_offset;
|
||||||
|
(void)limit_value;
|
||||||
|
|
||||||
|
memset(&range, 0, sizeof(range));
|
||||||
|
range.start_offset = from_offset;
|
||||||
|
range.next_offset = from_offset;
|
||||||
|
range.refs = NULL;
|
||||||
|
range.refs_len = 0u;
|
||||||
|
|
||||||
|
if (limit == 0u || amduat_asl_none_is_artifact(&inputs[0])) {
|
||||||
|
goto encode_range;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
amduat_asl_log_chunk_t *chunks = NULL;
|
||||||
|
size_t chunks_len = 0u;
|
||||||
|
amduat_asl_log_chunk_t head_chunk;
|
||||||
|
uint64_t head_end_offset = 0u;
|
||||||
|
if (!amduat_log_chunk_from_artifact(&inputs[0], &head_chunk)) {
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_LOG_CHUNK_INVALID;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (head_chunk.base_offset >
|
||||||
|
UINT64_MAX - (uint64_t)head_chunk.entry_count) {
|
||||||
|
amduat_asl_log_chunk_free(&head_chunk);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_LOG_CHUNK_INVALID;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
head_end_offset = head_chunk.base_offset + head_chunk.entry_count;
|
||||||
|
|
||||||
|
{
|
||||||
|
amduat_asl_log_chunk_t *next =
|
||||||
|
(amduat_asl_log_chunk_t *)realloc(
|
||||||
|
chunks, (chunks_len + 1u) * sizeof(*chunks));
|
||||||
|
if (next == NULL) {
|
||||||
|
amduat_asl_log_chunk_free(&head_chunk);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
chunks = next;
|
||||||
|
chunks[chunks_len++] = head_chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from_offset >= head_end_offset) {
|
||||||
|
for (size_t i = 0u; i < chunks_len; ++i) {
|
||||||
|
amduat_asl_log_chunk_free(&chunks[i]);
|
||||||
|
}
|
||||||
|
free(chunks);
|
||||||
|
range.next_offset = from_offset;
|
||||||
|
goto encode_range;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
amduat_asl_log_chunk_t chunk;
|
||||||
|
amduat_artifact_t prev_artifact;
|
||||||
|
|
||||||
|
if (chunks[chunks_len - 1u].base_offset <= from_offset ||
|
||||||
|
!chunks[chunks_len - 1u].has_prev) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&prev_artifact, 0, sizeof(prev_artifact));
|
||||||
|
if (!amduat_pel_kernel_resolve_artifact(
|
||||||
|
chunks[chunks_len - 1u].prev_ref, &prev_artifact)) {
|
||||||
|
for (size_t i = 0u; i < chunks_len; ++i) {
|
||||||
|
amduat_asl_log_chunk_free(&chunks[i]);
|
||||||
|
}
|
||||||
|
free(chunks);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_REF_RESOLVE_FAILED;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_log_chunk_from_artifact(&prev_artifact, &chunk)) {
|
||||||
|
amduat_artifact_free(&prev_artifact);
|
||||||
|
for (size_t i = 0u; i < chunks_len; ++i) {
|
||||||
|
amduat_asl_log_chunk_free(&chunks[i]);
|
||||||
|
}
|
||||||
|
free(chunks);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_LOG_CHUNK_INVALID;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
amduat_artifact_free(&prev_artifact);
|
||||||
|
|
||||||
|
{
|
||||||
|
amduat_asl_log_chunk_t *next =
|
||||||
|
(amduat_asl_log_chunk_t *)realloc(
|
||||||
|
chunks, (chunks_len + 1u) * sizeof(*chunks));
|
||||||
|
if (next == NULL) {
|
||||||
|
amduat_asl_log_chunk_free(&chunk);
|
||||||
|
for (size_t i = 0u; i < chunks_len; ++i) {
|
||||||
|
amduat_asl_log_chunk_free(&chunks[i]);
|
||||||
|
}
|
||||||
|
free(chunks);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
chunks = next;
|
||||||
|
chunks[chunks_len++] = chunk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (limit > SIZE_MAX) {
|
||||||
|
for (size_t i = 0u; i < chunks_len; ++i) {
|
||||||
|
amduat_asl_log_chunk_free(&chunks[i]);
|
||||||
|
}
|
||||||
|
free(chunks);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_LOG_RANGE_INVALID;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (limit != 0u) {
|
||||||
|
range.refs = (amduat_reference_t *)calloc(limit, sizeof(*range.refs));
|
||||||
|
if (range.refs == NULL) {
|
||||||
|
for (size_t i = 0u; i < chunks_len; ++i) {
|
||||||
|
amduat_asl_log_chunk_free(&chunks[i]);
|
||||||
|
}
|
||||||
|
free(chunks);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0u; i < chunks_len / 2u; ++i) {
|
||||||
|
amduat_asl_log_chunk_t tmp = chunks[i];
|
||||||
|
chunks[i] = chunks[chunks_len - 1u - i];
|
||||||
|
chunks[chunks_len - 1u - i] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
range.refs_len = 0u;
|
||||||
|
for (size_t i = 0u; i < chunks_len; ++i) {
|
||||||
|
amduat_asl_log_chunk_t *chunk = &chunks[i];
|
||||||
|
for (uint32_t j = 0u; j < chunk->entry_count; ++j) {
|
||||||
|
uint64_t offset = chunk->base_offset + j;
|
||||||
|
if (offset < from_offset) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (range.refs_len == limit) {
|
||||||
|
goto done_collect;
|
||||||
|
}
|
||||||
|
if (!amduat_reference_clone(chunk->entries[j].payload_ref,
|
||||||
|
&range.refs[range.refs_len])) {
|
||||||
|
for (size_t k = 0u; k < chunks_len; ++k) {
|
||||||
|
amduat_asl_log_chunk_free(&chunks[k]);
|
||||||
|
}
|
||||||
|
free(chunks);
|
||||||
|
amduat_asl_log_range_free(&range);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
range.refs_len++;
|
||||||
|
range.next_offset = offset + 1u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done_collect:
|
||||||
|
if (range.refs_len < limit) {
|
||||||
|
range.next_offset = head_end_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0u; i < chunks_len; ++i) {
|
||||||
|
amduat_asl_log_chunk_free(&chunks[i]);
|
||||||
|
}
|
||||||
|
free(chunks);
|
||||||
|
}
|
||||||
|
|
||||||
|
encode_range:
|
||||||
|
if (!amduat_asl_log_range_encode_v1(&range, &encoded)) {
|
||||||
|
amduat_asl_log_range_free(&range);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_alloc_outputs(1u, out_outputs)) {
|
||||||
|
amduat_asl_log_range_free(&range);
|
||||||
|
free((void *)encoded.data);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*out_outputs)[0] = amduat_artifact_with_type(
|
||||||
|
encoded, amduat_type_tag(AMDUAT_TYPE_TAG_ASL_LOG_RANGE_1));
|
||||||
|
if (out_outputs_len != NULL) {
|
||||||
|
*out_outputs_len = 1u;
|
||||||
|
}
|
||||||
|
ok = true;
|
||||||
|
amduat_asl_log_range_free(&range);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_kernel_collection_merge_refs(
|
||||||
|
const amduat_artifact_t *inputs,
|
||||||
|
size_t inputs_len,
|
||||||
|
amduat_artifact_t **out_outputs,
|
||||||
|
size_t *out_outputs_len,
|
||||||
|
uint32_t *out_status_code) {
|
||||||
|
amduat_asl_collection_snapshot_info_t snapshot;
|
||||||
|
amduat_asl_log_range_t log_range;
|
||||||
|
amduat_asl_collection_view_t view;
|
||||||
|
amduat_octets_t encoded = amduat_octets(NULL, 0u);
|
||||||
|
uint64_t from_offset = 0u;
|
||||||
|
uint32_t limit = 0u;
|
||||||
|
uint64_t limit_from_offset = 0u;
|
||||||
|
uint32_t limit_value = 0u;
|
||||||
|
size_t total_refs = 0u;
|
||||||
|
size_t start_index = 0u;
|
||||||
|
size_t end_index = 0u;
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
if (inputs == NULL || inputs_len != 4u) {
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_INTERNAL;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_decode_params(&inputs[2], &from_offset, &limit_value) ||
|
||||||
|
!amduat_decode_params(&inputs[3], &limit_from_offset, &limit)) {
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_PARAMS_INVALID;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
(void)limit_from_offset;
|
||||||
|
(void)limit_value;
|
||||||
|
|
||||||
|
memset(&snapshot, 0, sizeof(snapshot));
|
||||||
|
memset(&log_range, 0, sizeof(log_range));
|
||||||
|
memset(&view, 0, sizeof(view));
|
||||||
|
|
||||||
|
if (!inputs[0].has_type_tag ||
|
||||||
|
inputs[0].type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_SNAPSHOT_INFO_1 ||
|
||||||
|
!amduat_asl_collection_snapshot_info_decode_v1(inputs[0].bytes,
|
||||||
|
&snapshot)) {
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!inputs[1].has_type_tag ||
|
||||||
|
inputs[1].type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_LOG_RANGE_1 ||
|
||||||
|
!amduat_asl_log_range_decode_v1(inputs[1].bytes, &log_range)) {
|
||||||
|
amduat_asl_collection_snapshot_info_free(&snapshot);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_LOG_RANGE_INVALID;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snapshot.refs_len > SIZE_MAX - log_range.refs_len) {
|
||||||
|
amduat_asl_collection_snapshot_info_free(&snapshot);
|
||||||
|
amduat_asl_log_range_free(&log_range);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_VIEW_INVALID;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
total_refs = snapshot.refs_len + log_range.refs_len;
|
||||||
|
if (from_offset > SIZE_MAX) {
|
||||||
|
start_index = total_refs;
|
||||||
|
} else {
|
||||||
|
start_index = (size_t)from_offset;
|
||||||
|
if (start_index > total_refs) {
|
||||||
|
start_index = total_refs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (limit > SIZE_MAX || start_index > SIZE_MAX - (size_t)limit) {
|
||||||
|
end_index = total_refs;
|
||||||
|
} else {
|
||||||
|
end_index = start_index + (size_t)limit;
|
||||||
|
if (end_index > total_refs) {
|
||||||
|
end_index = total_refs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
view.refs_len = end_index - start_index;
|
||||||
|
view.refs = NULL;
|
||||||
|
if (view.refs_len != 0u) {
|
||||||
|
view.refs = (amduat_reference_t *)calloc(view.refs_len, sizeof(*view.refs));
|
||||||
|
if (view.refs == NULL) {
|
||||||
|
amduat_asl_collection_snapshot_info_free(&snapshot);
|
||||||
|
amduat_asl_log_range_free(&log_range);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0u; i < view.refs_len; ++i) {
|
||||||
|
size_t idx = start_index + i;
|
||||||
|
const amduat_reference_t *src =
|
||||||
|
(idx < snapshot.refs_len)
|
||||||
|
? &snapshot.refs[idx]
|
||||||
|
: &log_range.refs[idx - snapshot.refs_len];
|
||||||
|
if (!amduat_reference_clone(*src, &view.refs[i])) {
|
||||||
|
amduat_asl_collection_view_free(&view);
|
||||||
|
amduat_asl_collection_snapshot_info_free(&snapshot);
|
||||||
|
amduat_asl_log_range_free(&log_range);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
view.computed_from_offset = from_offset;
|
||||||
|
if (log_range.refs_len < limit) {
|
||||||
|
view.computed_up_to_offset = log_range.next_offset;
|
||||||
|
} else if (from_offset > UINT64_MAX - (uint64_t)view.refs_len) {
|
||||||
|
view.computed_up_to_offset = UINT64_MAX;
|
||||||
|
} else {
|
||||||
|
view.computed_up_to_offset = from_offset + (uint64_t)view.refs_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_asl_collection_view_encode_v1(&view, &encoded)) {
|
||||||
|
amduat_asl_collection_view_free(&view);
|
||||||
|
amduat_asl_collection_snapshot_info_free(&snapshot);
|
||||||
|
amduat_asl_log_range_free(&log_range);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_alloc_outputs(1u, out_outputs)) {
|
||||||
|
amduat_asl_collection_view_free(&view);
|
||||||
|
amduat_asl_collection_snapshot_info_free(&snapshot);
|
||||||
|
amduat_asl_log_range_free(&log_range);
|
||||||
|
free((void *)encoded.data);
|
||||||
|
if (out_status_code) {
|
||||||
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*out_outputs)[0] = amduat_artifact_with_type(
|
||||||
|
encoded, amduat_type_tag(AMDUAT_TYPE_TAG_ASL_COLLECTION_VIEW_1));
|
||||||
|
if (out_outputs_len != NULL) {
|
||||||
|
*out_outputs_len = 1u;
|
||||||
|
}
|
||||||
|
ok = true;
|
||||||
|
|
||||||
|
amduat_asl_collection_view_free(&view);
|
||||||
|
amduat_asl_collection_snapshot_info_free(&snapshot);
|
||||||
|
amduat_asl_log_range_free(&log_range);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
29
src/pel_stack/opreg/kernel_collection.h
Normal file
29
src/pel_stack/opreg/kernel_collection.h
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef AMDUAT_PEL_OPREG_KERNEL_COLLECTION_H
|
||||||
|
#define AMDUAT_PEL_OPREG_KERNEL_COLLECTION_H
|
||||||
|
|
||||||
|
#include "amduat/pel/opreg_kernel.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
bool amduat_kernel_collection_snapshot_decode(
|
||||||
|
const amduat_artifact_t *inputs,
|
||||||
|
size_t inputs_len,
|
||||||
|
amduat_artifact_t **out_outputs,
|
||||||
|
size_t *out_outputs_len,
|
||||||
|
uint32_t *out_status_code);
|
||||||
|
|
||||||
|
bool amduat_kernel_log_read_range(
|
||||||
|
const amduat_artifact_t *inputs,
|
||||||
|
size_t inputs_len,
|
||||||
|
amduat_artifact_t **out_outputs,
|
||||||
|
size_t *out_outputs_len,
|
||||||
|
uint32_t *out_status_code);
|
||||||
|
|
||||||
|
bool amduat_kernel_collection_merge_refs(
|
||||||
|
const amduat_artifact_t *inputs,
|
||||||
|
size_t inputs_len,
|
||||||
|
amduat_artifact_t **out_outputs,
|
||||||
|
size_t *out_outputs_len,
|
||||||
|
uint32_t *out_status_code);
|
||||||
|
|
||||||
|
#endif /* AMDUAT_PEL_OPREG_KERNEL_COLLECTION_H */
|
||||||
|
|
@ -133,6 +133,12 @@ bool amduat_pel_kernel_params_decode(
|
||||||
return amduat_decode_unit(params_bytes);
|
return amduat_decode_unit(params_bytes);
|
||||||
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
|
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
|
||||||
return amduat_decode_unit(params_bytes);
|
return amduat_decode_unit(params_bytes);
|
||||||
|
case AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE:
|
||||||
|
return amduat_decode_unit(params_bytes);
|
||||||
|
case AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE:
|
||||||
|
return amduat_decode_unit(params_bytes);
|
||||||
|
case AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS:
|
||||||
|
return amduat_decode_unit(params_bytes);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include "amduat/enc/pel_program_dag.h"
|
#include "amduat/enc/pel_program_dag.h"
|
||||||
#include "amduat/enc/pel_trace_dag.h"
|
#include "amduat/enc/pel_trace_dag.h"
|
||||||
#include "amduat/pel/derivation_sid.h"
|
#include "amduat/pel/derivation_sid.h"
|
||||||
|
#include "amduat/pel/opreg_kernel.h"
|
||||||
#include "amduat/util/log.h"
|
#include "amduat/util/log.h"
|
||||||
#include "pel_program_dag_internal.h"
|
#include "pel_program_dag_internal.h"
|
||||||
#include "amduat/pel/program_dag_desc.h"
|
#include "amduat/pel/program_dag_desc.h"
|
||||||
|
|
@ -35,6 +36,17 @@ void amduat_pel_surf_free_ref(amduat_reference_t *ref) {
|
||||||
amduat_reference_free(ref);
|
amduat_reference_free(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool amduat_pel_surf_resolve_artifact(amduat_reference_t ref,
|
||||||
|
amduat_artifact_t *out_artifact,
|
||||||
|
void *ctx) {
|
||||||
|
amduat_asl_store_t *store = (amduat_asl_store_t *)ctx;
|
||||||
|
if (store == NULL || out_artifact == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return amduat_asl_store_get(store, ref, out_artifact) ==
|
||||||
|
AMDUAT_ASL_STORE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static void amduat_init_core_result(amduat_pel_execution_result_value_t *result,
|
static void amduat_init_core_result(amduat_pel_execution_result_value_t *result,
|
||||||
amduat_reference_t scheme_ref,
|
amduat_reference_t scheme_ref,
|
||||||
amduat_pel_execution_status_t status,
|
amduat_pel_execution_status_t status,
|
||||||
|
|
@ -691,9 +703,12 @@ bool amduat_pel_surf_run(amduat_asl_store_t *store,
|
||||||
program_decoded = true;
|
program_decoded = true;
|
||||||
const amduat_artifact_t *params_arg =
|
const amduat_artifact_t *params_arg =
|
||||||
has_params_artifact ? ¶ms_artifact : NULL;
|
has_params_artifact ? ¶ms_artifact : NULL;
|
||||||
|
amduat_pel_kernel_set_artifact_resolver(
|
||||||
|
amduat_pel_surf_resolve_artifact, store);
|
||||||
if (!amduat_pel_program_dag_exec_trace(
|
if (!amduat_pel_program_dag_exec_trace(
|
||||||
&program, input_artifacts, input_refs_len, params_arg, &outputs,
|
&program, input_artifacts, input_refs_len, params_arg, &outputs,
|
||||||
&outputs_len, &core_result, &trace_eval)) {
|
&outputs_len, &core_result, &trace_eval)) {
|
||||||
|
amduat_pel_kernel_clear_artifact_resolver();
|
||||||
amduat_artifact_free(&program_artifact);
|
amduat_artifact_free(&program_artifact);
|
||||||
amduat_enc_pel_program_dag_free(&program);
|
amduat_enc_pel_program_dag_free(&program);
|
||||||
for (i = 0; i < input_refs_len; ++i) {
|
for (i = 0; i < input_refs_len; ++i) {
|
||||||
|
|
@ -706,6 +721,7 @@ bool amduat_pel_surf_run(amduat_asl_store_t *store,
|
||||||
amduat_pel_program_dag_free_outputs(outputs, outputs_len);
|
amduat_pel_program_dag_free_outputs(outputs, outputs_len);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
amduat_pel_kernel_clear_artifact_resolver();
|
||||||
executed = true;
|
executed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
#include "amduat/asl/asl_pointer_fs.h"
|
#include "amduat/asl/asl_pointer_fs.h"
|
||||||
#include "amduat/asl/log_store.h"
|
#include "amduat/asl/log_store.h"
|
||||||
#include "amduat/asl/collection.h"
|
#include "amduat/asl/collection.h"
|
||||||
|
#include "amduat/asl/collection_view.h"
|
||||||
|
#include "amduat/asl/none.h"
|
||||||
#include "amduat/asl/record.h"
|
#include "amduat/asl/record.h"
|
||||||
#include "amduat/asl/asl_store_fs.h"
|
#include "amduat/asl/asl_store_fs.h"
|
||||||
#include "amduat/asl/asl_store_fs_meta.h"
|
#include "amduat/asl/asl_store_fs_meta.h"
|
||||||
|
|
@ -74,6 +76,8 @@ static void amduat_pel_cli_print_usage(FILE *stream) {
|
||||||
" result Surface result tools (decode).\n"
|
" result Surface result tools (decode).\n"
|
||||||
" op Kernel op registry tools.\n"
|
" op Kernel op registry tools.\n"
|
||||||
" log Append-only log tools (append, read).\n"
|
" log Append-only log tools (append, read).\n"
|
||||||
|
" col Collection tools (append, snapshot, read, view).\n"
|
||||||
|
" rec ASL record tools (put, get).\n"
|
||||||
" matcache Materialization cache tools (get, sid).\n"
|
" matcache Materialization cache tools (get, sid).\n"
|
||||||
" ptr Named pointer tools (get, cas).\n"
|
" ptr Named pointer tools (get, cas).\n"
|
||||||
" scheme Scheme refs, type tags, profile IDs.\n"
|
" scheme Scheme refs, type tags, profile IDs.\n"
|
||||||
|
|
@ -145,6 +149,14 @@ static void amduat_pel_cli_print_usage(FILE *stream) {
|
||||||
" amduat-pel log append --log NAME --kind N --ref REF [--actor TEXT]\n"
|
" amduat-pel log append --log NAME --kind N --ref REF [--actor TEXT]\n"
|
||||||
" amduat-pel log read --log NAME --from OFFSET --limit N\n"
|
" amduat-pel log read --log NAME --from OFFSET --limit N\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
"col:\n"
|
||||||
|
" amduat-pel col append --name NAME --record-ref REF [--kind N]\n"
|
||||||
|
" [--actor TEXT]\n"
|
||||||
|
" amduat-pel col snapshot --name NAME [--up-to OFFSET]\n"
|
||||||
|
" amduat-pel col read --name NAME --from OFFSET --limit N\n"
|
||||||
|
" amduat-pel col view --name NAME --from OFFSET --limit N\n"
|
||||||
|
" [--dump-program-ref]\n"
|
||||||
|
"\n"
|
||||||
"scheme:\n"
|
"scheme:\n"
|
||||||
" amduat-pel scheme show [--format text|json] [--ref-format hex|bytes]\n"
|
" amduat-pel scheme show [--format text|json] [--ref-format hex|bytes]\n"
|
||||||
" amduat-pel scheme dag-ref [--format hex|bytes]\n"
|
" amduat-pel scheme dag-ref [--format hex|bytes]\n"
|
||||||
|
|
@ -173,7 +185,8 @@ static void amduat_pel_cli_print_usage(FILE *stream) {
|
||||||
" - Only PEL/PROGRAM-DAG/1 is supported; other scheme refs yield SCHEME_UNSUPPORTED.\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"
|
" - Expected type tags: program 0x00000101, trace 0x00000102, result 0x00000103.\n"
|
||||||
" - Encoding profile IDs: program 0x0101, trace 0x0102, result 0x0103.\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, pel.bytes.params, pel.format.encode.\n"
|
" - Kernel ops: pel.bytes.concat, pel.bytes.slice, pel.bytes.const, pel.bytes.hash.asl1, pel.bytes.params, pel.format.encode,\n"
|
||||||
|
" collection.snapshot_decode_v1, log.read_range_v1, collection.merge_refs_v1.\n"
|
||||||
" - --ref-format bytes expects REF arguments to be a path or '-' (raw reference bytes).\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"
|
" - --inputs-file with --ref-format bytes expects raw concatenated references.\n"
|
||||||
" - run stores derivation records for outputs; use --no-index to skip.\n");
|
" - run stores derivation records for outputs; use --no-index to skip.\n");
|
||||||
|
|
@ -3230,6 +3243,232 @@ static bool amduat_pel_cli_init_store(const char *root,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool amduat_pel_cli_build_collection_head_name(const char *name,
|
||||||
|
char **out_name) {
|
||||||
|
size_t name_len;
|
||||||
|
size_t total_len;
|
||||||
|
char *buffer;
|
||||||
|
size_t offset = 0u;
|
||||||
|
|
||||||
|
if (name == NULL || out_name == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_pointer_name_is_valid(name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
name_len = strlen(name);
|
||||||
|
total_len = 11u + name_len + 5u + 1u;
|
||||||
|
buffer = (char *)malloc(total_len);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy(buffer + offset, "collection/", 11u);
|
||||||
|
offset += 11u;
|
||||||
|
memcpy(buffer + offset, name, name_len);
|
||||||
|
offset += name_len;
|
||||||
|
memcpy(buffer + offset, "/head", 5u);
|
||||||
|
offset += 5u;
|
||||||
|
buffer[offset] = '\0';
|
||||||
|
*out_name = buffer;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_pel_cli_build_collection_log_head_name(const char *name,
|
||||||
|
char **out_name) {
|
||||||
|
size_t name_len;
|
||||||
|
size_t log_name_len;
|
||||||
|
size_t total_len;
|
||||||
|
char *buffer;
|
||||||
|
size_t offset = 0u;
|
||||||
|
|
||||||
|
if (name == NULL || out_name == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_pointer_name_is_valid(name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
name_len = strlen(name);
|
||||||
|
log_name_len = 11u + name_len + 4u;
|
||||||
|
total_len = 4u + log_name_len + 5u + 1u;
|
||||||
|
buffer = (char *)malloc(total_len);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy(buffer + offset, "log/", 4u);
|
||||||
|
offset += 4u;
|
||||||
|
memcpy(buffer + offset, "collection/", 11u);
|
||||||
|
offset += 11u;
|
||||||
|
memcpy(buffer + offset, name, name_len);
|
||||||
|
offset += name_len;
|
||||||
|
memcpy(buffer + offset, "/log", 4u);
|
||||||
|
offset += 4u;
|
||||||
|
memcpy(buffer + offset, "/head", 5u);
|
||||||
|
offset += 5u;
|
||||||
|
buffer[offset] = '\0';
|
||||||
|
*out_name = buffer;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_pel_cli_get_none_ref(amduat_asl_store_t *store,
|
||||||
|
amduat_reference_t *out_ref) {
|
||||||
|
amduat_artifact_t none_artifact;
|
||||||
|
|
||||||
|
if (store == NULL || out_ref == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_none_artifact(&none_artifact)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (amduat_asl_store_put(store, none_artifact, out_ref) !=
|
||||||
|
AMDUAT_ASL_STORE_OK) {
|
||||||
|
amduat_artifact_free(&none_artifact);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
amduat_artifact_free(&none_artifact);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_pel_cli_put_view_params(amduat_asl_store_t *store,
|
||||||
|
uint64_t from_offset,
|
||||||
|
uint32_t limit,
|
||||||
|
amduat_reference_t *out_ref) {
|
||||||
|
uint8_t payload[12];
|
||||||
|
amduat_asl_record_t record;
|
||||||
|
|
||||||
|
if (store == NULL || out_ref == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
payload[0] = (uint8_t)(from_offset & 0xffu);
|
||||||
|
payload[1] = (uint8_t)((from_offset >> 8) & 0xffu);
|
||||||
|
payload[2] = (uint8_t)((from_offset >> 16) & 0xffu);
|
||||||
|
payload[3] = (uint8_t)((from_offset >> 24) & 0xffu);
|
||||||
|
payload[4] = (uint8_t)((from_offset >> 32) & 0xffu);
|
||||||
|
payload[5] = (uint8_t)((from_offset >> 40) & 0xffu);
|
||||||
|
payload[6] = (uint8_t)((from_offset >> 48) & 0xffu);
|
||||||
|
payload[7] = (uint8_t)((from_offset >> 56) & 0xffu);
|
||||||
|
payload[8] = (uint8_t)(limit & 0xffu);
|
||||||
|
payload[9] = (uint8_t)((limit >> 8) & 0xffu);
|
||||||
|
payload[10] = (uint8_t)((limit >> 16) & 0xffu);
|
||||||
|
payload[11] = (uint8_t)((limit >> 24) & 0xffu);
|
||||||
|
|
||||||
|
record.schema = amduat_octets("pel/params", strlen("pel/params"));
|
||||||
|
record.payload = amduat_octets(payload, sizeof(payload));
|
||||||
|
|
||||||
|
if (amduat_asl_record_store_put(store,
|
||||||
|
record.schema,
|
||||||
|
record.payload,
|
||||||
|
out_ref) != AMDUAT_ASL_STORE_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amduat_pel_cli_program_free(amduat_pel_program_t *program) {
|
||||||
|
if (program == NULL || program->nodes == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0u; i < program->nodes_len; ++i) {
|
||||||
|
free(program->nodes[i].inputs);
|
||||||
|
}
|
||||||
|
free(program->nodes);
|
||||||
|
free(program->roots);
|
||||||
|
program->nodes = NULL;
|
||||||
|
program->roots = NULL;
|
||||||
|
program->nodes_len = 0u;
|
||||||
|
program->roots_len = 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_pel_cli_build_collection_view_program(
|
||||||
|
amduat_pel_program_t *out_program) {
|
||||||
|
static const char k_op_snapshot[] = "collection.snapshot_decode_v1";
|
||||||
|
static const char k_op_read_range[] = "log.read_range_v1";
|
||||||
|
static const char k_op_merge[] = "collection.merge_refs_v1";
|
||||||
|
amduat_pel_node_t *nodes;
|
||||||
|
amduat_pel_root_ref_t *roots;
|
||||||
|
|
||||||
|
if (out_program == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memset(out_program, 0, sizeof(*out_program));
|
||||||
|
|
||||||
|
nodes = (amduat_pel_node_t *)calloc(3u, sizeof(*nodes));
|
||||||
|
roots = (amduat_pel_root_ref_t *)calloc(1u, sizeof(*roots));
|
||||||
|
if (nodes == NULL || roots == NULL) {
|
||||||
|
free(nodes);
|
||||||
|
free(roots);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes[0].id = 1u;
|
||||||
|
nodes[0].op.name = amduat_octets(k_op_snapshot, strlen(k_op_snapshot));
|
||||||
|
nodes[0].op.version = 1u;
|
||||||
|
nodes[0].inputs_len = 1u;
|
||||||
|
nodes[0].inputs =
|
||||||
|
(amduat_pel_dag_input_t *)calloc(1u, sizeof(*nodes[0].inputs));
|
||||||
|
if (nodes[0].inputs == NULL) {
|
||||||
|
free(nodes);
|
||||||
|
free(roots);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nodes[0].inputs[0].kind = AMDUAT_PEL_DAG_INPUT_EXTERNAL;
|
||||||
|
nodes[0].inputs[0].value.external.input_index = 0u;
|
||||||
|
nodes[0].params = amduat_octets(NULL, 0u);
|
||||||
|
|
||||||
|
nodes[1].id = 2u;
|
||||||
|
nodes[1].op.name = amduat_octets(k_op_read_range, strlen(k_op_read_range));
|
||||||
|
nodes[1].op.version = 1u;
|
||||||
|
nodes[1].inputs_len = 3u;
|
||||||
|
nodes[1].inputs =
|
||||||
|
(amduat_pel_dag_input_t *)calloc(3u, sizeof(*nodes[1].inputs));
|
||||||
|
if (nodes[1].inputs == NULL) {
|
||||||
|
free(nodes[0].inputs);
|
||||||
|
free(nodes);
|
||||||
|
free(roots);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nodes[1].inputs[0].kind = AMDUAT_PEL_DAG_INPUT_EXTERNAL;
|
||||||
|
nodes[1].inputs[0].value.external.input_index = 1u;
|
||||||
|
nodes[1].inputs[1].kind = AMDUAT_PEL_DAG_INPUT_EXTERNAL;
|
||||||
|
nodes[1].inputs[1].value.external.input_index = 2u;
|
||||||
|
nodes[1].inputs[2].kind = AMDUAT_PEL_DAG_INPUT_EXTERNAL;
|
||||||
|
nodes[1].inputs[2].value.external.input_index = 3u;
|
||||||
|
nodes[1].params = amduat_octets(NULL, 0u);
|
||||||
|
|
||||||
|
nodes[2].id = 3u;
|
||||||
|
nodes[2].op.name = amduat_octets(k_op_merge, strlen(k_op_merge));
|
||||||
|
nodes[2].op.version = 1u;
|
||||||
|
nodes[2].inputs_len = 4u;
|
||||||
|
nodes[2].inputs =
|
||||||
|
(amduat_pel_dag_input_t *)calloc(4u, sizeof(*nodes[2].inputs));
|
||||||
|
if (nodes[2].inputs == NULL) {
|
||||||
|
free(nodes[1].inputs);
|
||||||
|
free(nodes[0].inputs);
|
||||||
|
free(nodes);
|
||||||
|
free(roots);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nodes[2].inputs[0].kind = AMDUAT_PEL_DAG_INPUT_NODE;
|
||||||
|
nodes[2].inputs[0].value.node.node_id = 1u;
|
||||||
|
nodes[2].inputs[0].value.node.output_index = 0u;
|
||||||
|
nodes[2].inputs[1].kind = AMDUAT_PEL_DAG_INPUT_NODE;
|
||||||
|
nodes[2].inputs[1].value.node.node_id = 2u;
|
||||||
|
nodes[2].inputs[1].value.node.output_index = 0u;
|
||||||
|
nodes[2].inputs[2].kind = AMDUAT_PEL_DAG_INPUT_EXTERNAL;
|
||||||
|
nodes[2].inputs[2].value.external.input_index = 2u;
|
||||||
|
nodes[2].inputs[3].kind = AMDUAT_PEL_DAG_INPUT_EXTERNAL;
|
||||||
|
nodes[2].inputs[3].value.external.input_index = 3u;
|
||||||
|
nodes[2].params = amduat_octets(NULL, 0u);
|
||||||
|
|
||||||
|
roots[0].node_id = 3u;
|
||||||
|
roots[0].output_index = 0u;
|
||||||
|
|
||||||
|
out_program->nodes = nodes;
|
||||||
|
out_program->nodes_len = 3u;
|
||||||
|
out_program->roots = roots;
|
||||||
|
out_program->roots_len = 1u;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static int amduat_pel_cli_cmd_log_append(
|
static int amduat_pel_cli_cmd_log_append(
|
||||||
int argc,
|
int argc,
|
||||||
char **argv,
|
char **argv,
|
||||||
|
|
@ -3895,6 +4134,283 @@ static int amduat_pel_cli_cmd_col_read(
|
||||||
return AMDUAT_PEL_CLI_EXIT_OK;
|
return AMDUAT_PEL_CLI_EXIT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int amduat_pel_cli_cmd_col_view(
|
||||||
|
int argc,
|
||||||
|
char **argv,
|
||||||
|
const amduat_pel_cli_global_opts_t *global) {
|
||||||
|
const char *name = NULL;
|
||||||
|
uint64_t from = 0u;
|
||||||
|
unsigned long long limit = 0u;
|
||||||
|
bool dump_program_ref = false;
|
||||||
|
amduat_asl_store_t store;
|
||||||
|
amduat_asl_store_fs_t fs;
|
||||||
|
amduat_asl_pointer_store_t pointer_store;
|
||||||
|
amduat_reference_t snapshot_ref;
|
||||||
|
amduat_reference_t log_head_ref;
|
||||||
|
amduat_reference_t none_ref;
|
||||||
|
amduat_reference_t params_ref;
|
||||||
|
amduat_reference_t program_ref;
|
||||||
|
amduat_reference_t input_refs[4];
|
||||||
|
amduat_pel_program_t program;
|
||||||
|
amduat_octets_t program_bytes = amduat_octets(NULL, 0u);
|
||||||
|
amduat_pel_run_result_t run_result;
|
||||||
|
amduat_artifact_t view_artifact;
|
||||||
|
amduat_asl_collection_view_t view;
|
||||||
|
amduat_type_tag_t expected_type_tag;
|
||||||
|
amduat_asl_encoding_profile_id_t expected_profile;
|
||||||
|
char *snapshot_name = NULL;
|
||||||
|
char *log_head_name = NULL;
|
||||||
|
bool snapshot_exists = false;
|
||||||
|
bool log_head_exists = false;
|
||||||
|
bool stdin_used = false;
|
||||||
|
int exit_code = AMDUAT_PEL_CLI_EXIT_OK;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (global == NULL) {
|
||||||
|
return AMDUAT_PEL_CLI_EXIT_USAGE;
|
||||||
|
}
|
||||||
|
memset(&snapshot_ref, 0, sizeof(snapshot_ref));
|
||||||
|
memset(&log_head_ref, 0, sizeof(log_head_ref));
|
||||||
|
memset(&none_ref, 0, sizeof(none_ref));
|
||||||
|
memset(¶ms_ref, 0, sizeof(params_ref));
|
||||||
|
memset(&program_ref, 0, sizeof(program_ref));
|
||||||
|
|
||||||
|
for (i = 0; i < argc; ++i) {
|
||||||
|
if (strcmp(argv[i], "--name") == 0) {
|
||||||
|
if (i + 1 >= argc) {
|
||||||
|
fprintf(stderr, "error: --name requires a value\n");
|
||||||
|
return AMDUAT_PEL_CLI_EXIT_USAGE;
|
||||||
|
}
|
||||||
|
name = argv[++i];
|
||||||
|
} else if (strcmp(argv[i], "--from") == 0) {
|
||||||
|
if (i + 1 >= argc) {
|
||||||
|
fprintf(stderr, "error: --from requires a value\n");
|
||||||
|
return AMDUAT_PEL_CLI_EXIT_USAGE;
|
||||||
|
}
|
||||||
|
from = (uint64_t)strtoull(argv[++i], NULL, 10);
|
||||||
|
} else if (strcmp(argv[i], "--limit") == 0) {
|
||||||
|
if (i + 1 >= argc) {
|
||||||
|
fprintf(stderr, "error: --limit requires a value\n");
|
||||||
|
return AMDUAT_PEL_CLI_EXIT_USAGE;
|
||||||
|
}
|
||||||
|
limit = strtoull(argv[++i], NULL, 10);
|
||||||
|
} else if (strcmp(argv[i], "--dump-program-ref") == 0) {
|
||||||
|
dump_program_ref = 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 (name == NULL || limit == 0u) {
|
||||||
|
fprintf(stderr, "error: --name and --limit are required\n");
|
||||||
|
return AMDUAT_PEL_CLI_EXIT_USAGE;
|
||||||
|
}
|
||||||
|
if (limit > UINT32_MAX) {
|
||||||
|
fprintf(stderr, "error: --limit out of range\n");
|
||||||
|
return AMDUAT_PEL_CLI_EXIT_USAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_pel_cli_init_store(global->root, &store, &fs)) {
|
||||||
|
fprintf(stderr, "error: failed to initialize store\n");
|
||||||
|
return AMDUAT_PEL_CLI_EXIT_CONFIG;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_pointer_store_init(&pointer_store, global->root)) {
|
||||||
|
fprintf(stderr, "error: failed to init pointer store\n");
|
||||||
|
return AMDUAT_PEL_CLI_EXIT_CONFIG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_pel_cli_get_none_ref(&store, &none_ref)) {
|
||||||
|
fprintf(stderr, "error: failed to create none artifact\n");
|
||||||
|
return AMDUAT_PEL_CLI_EXIT_STORE;
|
||||||
|
}
|
||||||
|
if (!amduat_pel_cli_build_collection_head_name(name, &snapshot_name) ||
|
||||||
|
!amduat_pel_cli_build_collection_log_head_name(name, &log_head_name)) {
|
||||||
|
fprintf(stderr, "error: invalid collection name\n");
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_USAGE;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (amduat_asl_pointer_get(&pointer_store, snapshot_name,
|
||||||
|
&snapshot_exists, &snapshot_ref) !=
|
||||||
|
AMDUAT_ASL_POINTER_OK) {
|
||||||
|
fprintf(stderr, "error: failed to read collection head\n");
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_IO;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
if (!snapshot_exists &&
|
||||||
|
!amduat_reference_clone(none_ref, &snapshot_ref)) {
|
||||||
|
fprintf(stderr, "error: failed to clone none ref\n");
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (amduat_asl_pointer_get(&pointer_store, log_head_name,
|
||||||
|
&log_head_exists, &log_head_ref) !=
|
||||||
|
AMDUAT_ASL_POINTER_OK) {
|
||||||
|
fprintf(stderr, "error: failed to read log head\n");
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_IO;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
if (!log_head_exists &&
|
||||||
|
!amduat_reference_clone(none_ref, &log_head_ref)) {
|
||||||
|
fprintf(stderr, "error: failed to clone none ref\n");
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_pel_cli_put_view_params(&store, from, (uint32_t)limit,
|
||||||
|
¶ms_ref)) {
|
||||||
|
fprintf(stderr, "error: failed to store params\n");
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_pel_cli_build_collection_view_program(&program)) {
|
||||||
|
fprintf(stderr, "error: failed to build program\n");
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_enc_pel_program_dag_encode_v1(&program, &program_bytes)) {
|
||||||
|
amduat_pel_cli_program_free(&program);
|
||||||
|
fprintf(stderr, "error: failed to encode program\n");
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
amduat_pel_cli_program_free(&program);
|
||||||
|
|
||||||
|
if (!amduat_pel_program_dag_desc_get_program_binding(&expected_type_tag,
|
||||||
|
&expected_profile)) {
|
||||||
|
fprintf(stderr, "error: failed to load program binding\n");
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
if (expected_profile != AMDUAT_PEL_ENC_PROGRAM_DAG_V1) {
|
||||||
|
fprintf(stderr, "error: unsupported program profile\n");
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_UNSUPPORTED;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
amduat_artifact_t program_artifact =
|
||||||
|
amduat_artifact_with_type(program_bytes, expected_type_tag);
|
||||||
|
if (amduat_asl_store_put(&store, program_artifact, &program_ref) !=
|
||||||
|
AMDUAT_ASL_STORE_OK) {
|
||||||
|
fprintf(stderr, "error: failed to store program\n");
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dump_program_ref) {
|
||||||
|
fputs("program_ref=", stdout);
|
||||||
|
if (!amduat_format_ref_write_text(stdout, program_ref,
|
||||||
|
global->ref_format)) {
|
||||||
|
fprintf(stderr, "error: failed to format program ref\n");
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
fputc('\n', stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
input_refs[0] = snapshot_ref;
|
||||||
|
input_refs[1] = log_head_ref;
|
||||||
|
input_refs[2] = params_ref;
|
||||||
|
input_refs[3] = params_ref;
|
||||||
|
|
||||||
|
memset(&run_result, 0, sizeof(run_result));
|
||||||
|
if (!amduat_pel_surf_run_with_result(&store,
|
||||||
|
amduat_pel_program_dag_scheme_ref(),
|
||||||
|
program_ref,
|
||||||
|
input_refs,
|
||||||
|
4u,
|
||||||
|
true,
|
||||||
|
params_ref,
|
||||||
|
&run_result)) {
|
||||||
|
fprintf(stderr, "error: PEL surface execution failed\n");
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!run_result.has_result_value ||
|
||||||
|
run_result.result_value.core_result.status != AMDUAT_PEL_EXEC_STATUS_OK) {
|
||||||
|
fprintf(stderr, "error: projection execution failed\n");
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
if (run_result.output_refs_len != 1u) {
|
||||||
|
fprintf(stderr, "error: unexpected output count\n");
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&view_artifact, 0, sizeof(view_artifact));
|
||||||
|
if (amduat_asl_store_get(&store, run_result.output_refs[0],
|
||||||
|
&view_artifact) != AMDUAT_ASL_STORE_OK) {
|
||||||
|
fprintf(stderr, "error: failed to load view artifact\n");
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_STORE;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
if (!view_artifact.has_type_tag ||
|
||||||
|
view_artifact.type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_COLLECTION_VIEW_1 ||
|
||||||
|
!amduat_asl_collection_view_decode_v1(view_artifact.bytes, &view)) {
|
||||||
|
amduat_artifact_free(&view_artifact);
|
||||||
|
fprintf(stderr, "error: invalid view artifact\n");
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
amduat_artifact_free(&view_artifact);
|
||||||
|
|
||||||
|
fputs("view_ref=", stdout);
|
||||||
|
if (!amduat_format_ref_write_text(stdout, run_result.output_refs[0],
|
||||||
|
global->ref_format)) {
|
||||||
|
fprintf(stderr, "error: failed to format view ref\n");
|
||||||
|
amduat_asl_collection_view_free(&view);
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
fputc('\n', stdout);
|
||||||
|
printf("computed_from_offset=%" PRIu64 "\n", view.computed_from_offset);
|
||||||
|
printf("computed_up_to_offset=%" PRIu64 "\n", view.computed_up_to_offset);
|
||||||
|
printf("entry_count=%zu\n", view.refs_len);
|
||||||
|
for (size_t idx = 0u; idx < view.refs_len; ++idx) {
|
||||||
|
fputs("entry_ref=", stdout);
|
||||||
|
if (!amduat_format_ref_write_text(stdout, view.refs[idx],
|
||||||
|
global->ref_format)) {
|
||||||
|
fprintf(stderr, "error: failed to format entry ref\n");
|
||||||
|
amduat_asl_collection_view_free(&view);
|
||||||
|
exit_code = AMDUAT_PEL_CLI_EXIT_CODEC;
|
||||||
|
goto view_cleanup;
|
||||||
|
}
|
||||||
|
fputc('\n', stdout);
|
||||||
|
}
|
||||||
|
amduat_asl_collection_view_free(&view);
|
||||||
|
|
||||||
|
view_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);
|
||||||
|
amduat_pel_cli_free_reference(&snapshot_ref);
|
||||||
|
amduat_pel_cli_free_reference(&log_head_ref);
|
||||||
|
amduat_pel_cli_free_reference(&none_ref);
|
||||||
|
amduat_pel_cli_free_reference(¶ms_ref);
|
||||||
|
amduat_pel_cli_free_reference(&program_ref);
|
||||||
|
free((void *)program_bytes.data);
|
||||||
|
free(snapshot_name);
|
||||||
|
free(log_head_name);
|
||||||
|
return exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
static int amduat_pel_cli_cmd_col(
|
static int amduat_pel_cli_cmd_col(
|
||||||
int argc,
|
int argc,
|
||||||
char **argv,
|
char **argv,
|
||||||
|
|
@ -3912,6 +4428,9 @@ static int amduat_pel_cli_cmd_col(
|
||||||
if (strcmp(argv[0], "read") == 0) {
|
if (strcmp(argv[0], "read") == 0) {
|
||||||
return amduat_pel_cli_cmd_col_read(argc - 1, argv + 1, global);
|
return amduat_pel_cli_cmd_col_read(argc - 1, argv + 1, global);
|
||||||
}
|
}
|
||||||
|
if (strcmp(argv[0], "view") == 0) {
|
||||||
|
return amduat_pel_cli_cmd_col_view(argc - 1, argv + 1, global);
|
||||||
|
}
|
||||||
fprintf(stderr, "error: unknown col subcommand: %s\n", argv[0]);
|
fprintf(stderr, "error: unknown col subcommand: %s\n", argv[0]);
|
||||||
return AMDUAT_PEL_CLI_EXIT_USAGE;
|
return AMDUAT_PEL_CLI_EXIT_USAGE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue