Skip to content

Commit

Permalink
wip: generating UNION callers with KVPU
Browse files Browse the repository at this point in the history
TODO:
1. Add internal functions through generate_leafs that use the extra
   datum pointer to handle the union parsing and emitting.
2. get building again
  • Loading branch information
williamcroberts committed Feb 29, 2024
1 parent 1d9deee commit 5a9ed91
Show file tree
Hide file tree
Showing 6 changed files with 899 additions and 921 deletions.
68 changes: 40 additions & 28 deletions script/yaml_mu_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,25 @@ def type_to_root(scalar_map: dict, scalar: CScalar) -> CScalar:
resolved = scalar
return resolved

def find_union_selector(parent_field_map: {str, CType}):

possible_selectors = [
key
for key, value in parent_field_map.items()
if isinstance(value, CScalar)
]

if len(possible_selectors) != 1:
if "type" in possible_selectors:
possible_selectors = [ "type" ]
else:
raise RuntimeError(
f"Unexpected, Cannot handle {len(possible_selectors)} union selectors"
)

found_selector = possible_selectors[0]
return found_selector


def generate_complex_code_gen(
cprsr: CTypeParser,
Expand Down Expand Up @@ -835,34 +854,26 @@ def generate_complex_code_gen(
if not name.startswith(prefix):
continue

if name == "TPMS_ATTEST":
pass

needed_protos.append(name)

emitters = []
parsers = []

field_map = type_.fields
# if it contains a TPMU subfield, we DROP the selector, so figure it out
found_selector = None
has_union_field = any(isinstance(x, CUnion) for x in field_map.values())
if has_union_field:
possible_selectors = [
key
for key, value in field_map.items()
if isinstance(value, CScalar)
]
if len(possible_selectors) != 1:
if "type" in possible_selectors:
possible_selectors = "type"
else:
raise RuntimeError(
f"Unexpected, Cannot handle {len(possible_selectors)} union selectors"
)
elif len(possible_selectors) == 1:
found_selector = possible_selectors[0]

# AFAICT a type containing TPMU's will only have one selector
found_unions = [ x for x in field_map.values() if isinstance(x, CUnion) ]
union_selector = find_union_selector(field_map) if found_unions else None

for field_name, field_type in field_map.items():
# TODO we don't want to call the default scalar handler if we have
# scalar names, ie TPM2_ALG_ID for sha256...

# We never directly consume or output the union selector
if field_name == union_selector:
continue

if isinstance(field_type, CScalar):
resolved_type = type_to_root(
scalar_type_map, scalar_type_map[field_type.name]
Expand All @@ -883,19 +894,21 @@ def generate_complex_code_gen(
else:
fn_name = f"yaml_internal_{resolved_type.name}"

if has_union_field and found_selector == field_name:
if isinstance(resolved_type, CUnion):

emitters.append(
f' KVP_ADD_MARSHAL("{field_name}", 0, NULL, NULL)'
f' KVPU_ADD_MARSHAL("{field_name}", sizeof(src->{union_selector}), &src->{union_selector}, yaml_internal_{resolved_type.name}_scalar_marshal, sizeof(src->{field_name}), &src->{field_name}, yaml_internal_{resolved_type.name}_marshal)'
)

parsers.append(
f' KVP_ADD_UNMARSHAL("{field_name}", 0, NULL, NULL)'
f' KVPU_ADD_UNMARSHAL("{field_name}", sizeof(tmp_dest.{union_selector}), &tmp_dest.{union_selector}, yaml_internal_{resolved_type.name}_scalar_unmarshal, sizeof(tmp_dest.{field_name}), &tmp_dest.{field_name}, {fn_name}_unmarshal)'
)

else:
emitters.append(
f' KVP_ADD_MARSHAL("{field_name}", sizeof(src->{field_name}), &src->{field_name}, {fn_name}_marshal)'
)

parsers.append(
f' KVP_ADD_UNMARSHAL("{field_name}", sizeof(tmp_dest.{field_name}), &tmp_dest.{field_name}, {fn_name}_unmarshal)'
)
Expand Down Expand Up @@ -1298,16 +1311,15 @@ def generate_protos(proj_root: str, needed_protos: list[str]):
cprsr, proj_root, "yaml-tpmt", "TPMT_", needed_protos, needed_leafs
)

# TODO generated leaf functions for UNIONS should unpack them and call the proper
# underlying method based on type.

# generate_union_code_gen(
# cprsr, proj_root, needed_protos, needed_leafs
# )

# TODO TPMU
# TODO TPML

# BILL PICK UP HERE
# TODO TPMU leafs should be "internal" and generated, this will also fix my TPMU TODO.
generate_leafs(cprsr, proj_root, needed_leafs)

generate_protos(proj_root, needed_protos)
9 changes: 7 additions & 2 deletions src/tss2-mu-yaml/yaml-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ struct datum {
};

struct key_value {
bool is_union;
const char *key;
datum value;
datum union_extra;
};

typedef struct write_data write_data;
Expand All @@ -53,8 +55,11 @@ struct parser_state {
#define FIELD_TYPE(type, field) typeof(((type *)NULL)->field)

/* Adding key values to the list for emitting (generating YAML) */
#define KVP_ADD_MARSHAL(k, s, v, m) {.key = k, .value = { .data = (void *)v, .size = s, .marshal = m }}
#define KVP_ADD_UNMARSHAL(k, s, v, u) {.key = k, .value = { .data = (void *)v, .size = s, .unmarshal = u }}
#define KVP_ADD_MARSHAL(k, s, v, m) {.is_union = false, .key = k, .value = { .data = (void *)v, .size = s, .marshal = m }, .union_extra = { 0 }}
#define KVP_ADD_UNMARSHAL(k, s, v, u) {.is_union = false, .key = k, .value = { .data = (void *)v, .size = s, .unmarshal = u }, .union_extra = { 0 }}

#define KVPU_ADD_MARSHAL(k, us, uv, um, s, v, m) {.is_union = true, .key = k, .union_extra = { .data = (void *)uv, .size = us, .marshal = um }, .value = { .data = (void *)v, .size = s, .masrhal = m }}
#define KVPU_ADD_UNMARSHAL(k, us, uv, uu, s, v, u) {.is_union = true, .key = k, .union_extra = { .data = (void *)uv, .size = us, .marshal = uu }, .value = { .data = (void *)v, .size = s, .unmarshal = u }}

#define return_yaml_rc(rc) do { if (!rc) { return yaml_to_tss2_rc(rc); } } while (0)

Expand Down
Loading

0 comments on commit 5a9ed91

Please sign in to comment.