public TpmStruct(TpmStruct src) : base(src) { Fields = src.Fields; DerivedFrom = src.DerivedFrom; Info = src.Info; }
string GetCommandReturnType(CommandFlavor gen, TpmStruct resp, string methodName, out string returnFieldName) { returnFieldName = null; if (gen == CommandFlavor.AsyncCommand) { return("void"); } string returnType = "void"; var respFields = resp.NonTagFields; if (ForceJustOneReturnParm.Contains(methodName)) { respFields = respFields.Take(1).ToArray(); } if (respFields.Count() > 1) { return(resp.Name); } if (respFields.Count() == 1) { returnFieldName = respFields[0].Name; returnType = TransType(respFields[0]); } return(returnType); }
public void GenMarshalingMethod(bool dirTo, TpmStruct s) { var fields = s.MarshalFields; if (s.DerivedFrom != null || fields.Count() == 0) { return; } string dir = dirTo ? "to" : "initFrom", proto = $"{dir}Tpm(buf: TpmBuffer): void"; var marshalOps = dirTo ? GetToTpmFieldsMarshalOps(fields) : GetFromTpmFieldsMarshalOps(fields); WriteComment("TpmMarshaller method"); if (marshalOps.Count == 1) { // Lay it out in a single line Write($"{proto} {{ {marshalOps[0]}; }}"); } else { Write(proto); TabIn("{"); foreach (var op in marshalOps) { Write($"{op};"); } TabOut("}", false); } } // GenMarshalingMethod()
} // GenUnions() void GenGetUnionSelector(TpmStruct s) { string selType = GetUnionMemberSelectorInfo(s, out string selVal); if (selType != null) { WriteComment("TpmUnion method"); Write($"GetUnionSelector(): {selType} {{ return {selVal}; }}"); } }
public TpmStruct(string typeName, string comment, TpmStruct derivedFrom = null, StructInfo info = null, bool customizedImpl = false) : base(typeName, comment) { Fields = new List <StructField>(); DerivedFrom = derivedFrom; Debug.Assert(DerivedFrom == null || TpmTypes.Contains(DerivedFrom.SpecName)); Info = info ?? new TpmStructInfo(); }
void GenGetUnionSelector(TpmStruct s, bool implementsUnionInterfaces = true) { string selType = GetUnionMemberSelectorInfo(s, out string selVal); if (selType != null) { string overrideFlavor = implementsUnionInterfaces ? "virtual" : "override"; Write(""); Write($"public {overrideFlavor} {selType} GetUnionSelector() {{ return {selVal}; }}"); } }
public UnionMember GetMemberOfType(TpmStruct s) { UnionMember elt = null; do { elt = GetElementOfType(s); s = s.DerivedFrom; } while (elt == null && s != null); return(elt); }
void GenGetUnionSelector(TpmStruct s) { string selType = GetUnionMemberSelectorInfo(s, out string selVal); if (selType != null) { Write(""); TabIn($"def GetUnionSelector({This}): # {selType}"); WriteComment("TpmUnion method"); Write($"return {selVal}"); TabOut(); } }
static void FixEnumTypeCollisions() { List <TpmStruct> toAdd = new List <TpmStruct>(); for (int j = 0; j < TpmTypes.TheTypes.Count; j++) { TpmType tp = TpmTypes.TheTypes[j]; if (!(tp is TpmUnion && tp.SpecName.IsOneOf(new string[] { "TPMU_PUBLIC_ID", "TPMU_SIGNATURE" }))) { continue; } // See if we have collisions. // Collided member types are converted into derived types by adding selector name to the base // type name. Struct that became a base one inherits from all the union interfaces, while // a derived struct only inherits from the base one and implements interfaces of the unions, // of which it is a member. // Base class B provides a union interface implementation only if this union contains a member // of type B. If a union U contains members of types derived from B, then B's implementation // of U's interface methods just throws NotImplementedException exception. TpmUnion u = (TpmUnion)tp; var dict = new Dictionary <string, UnionMember>(); foreach (UnionMember m in u.Members) { string typeName = m.Type.SpecName; string selectorName = m.SelectorValue.Name; if (dict.ContainsKey(typeName)) { // Collision detected. Debug.WriteLine("Collision in {0} [{1}] -- {2}", u.Name, selectorName, typeName); TpmStruct baseStruct = (TpmStruct)TpmTypes.Lookup(typeName); AddDerivedStruct(baseStruct, m, u, "Auto-derived from " + baseStruct.SpecName + " to provide unique GetUnionSelector() implementation"); if (dict[typeName] != null) { // Create the derived structure for the first occurrence. AddDerivedStruct(baseStruct, dict[typeName], u); // But do it only once... dict[typeName] = null; } } else { dict.Add(typeName, m); } } } } // FixEnumTypeCollisions()
/// <param name="unionField"> Name of the filed of a union interface type associated with the returned tag </param> /// <returns> Name of the union selector (tag) fieled or null </returns> public static string GetUnionSelectorFieldInfo(TpmStruct s, out string unionField) { unionField = null; var selectors = s.Fields.Where(f => f.MarshalType == MarshalType.UnionSelector); if (selectors.Count() == 0) { return(null); } // If a struct is a member of multiple unions, all of them are expected to use the same selector value unionField = selectors.First().Name; return(selectors.First().RelatedUnion.Name); }
/// <param name="selVal"> Upon return set to the value (qualified enum memeber) of the selector (or null). </param> /// <returns> Union selector type name if 's' is a member of a tagged union. Otherwise null. </returns> public static string GetUnionMemberSelectorInfo(TpmStruct s, out string selVal) { selVal = null; if (s.IsCmdStruct() || s.ContainingUnions.Count == 0) { return(null); } // If a struct is a member of multiple unions, all of them are expected to use the same selector value TpmUnion u = s.ContainingUnions.ElementAt(0); selVal = s.SpecName == TpmTypes.EmptyUnionBaseName ? TpmTypes.AlgNull : u.GetMemberOfType(s).SelectorValue.QualifiedName; return(GetUnionSelectorType(u)); }
// The serializer needs hints when embedded structs or unions are serialized/deserialized. // This function returns the referenced structure types for simple embedded structs and // interface members. IEnumerable <TpmType> GetKnownTypes(TpmStruct s) { var containedTypes = new List <TpmType>(); foreach (StructField f in s.Fields) { switch (f.MarshalType) { case MarshalType.Normal: case MarshalType.SizedStruct: case MarshalType.UnionSelector: if (f.Type is TpmStruct) { containedTypes.Add(f.Type); } else if (f.Type is TpmTypedef) { var tdt = f.Type.StripTypedefs(); if (tdt.IsElementary() || tdt.Name == "KeyBits") { continue; } if (!containedTypes.Contains(tdt)) { containedTypes.Add(tdt); } } else if (f.Type is TpmEnum || f.Type is TpmBitfield) { if (!containedTypes.Contains(f.Type)) { containedTypes.Add(f.Type); } } break; case MarshalType.UnionObject: var unionMembers = (f.Type as TpmUnion).Members.Select(um => um.Type); containedTypes = containedTypes.Union(unionMembers).ToList(); break; default: continue; } } return(containedTypes.OrderBy(t => t.SpecName)); }
void GenCommand(TpmStruct req, CommandFlavor gen) { var resp = GetRespStruct(req); string cmdName = GetCommandName(req); if (gen == CommandFlavor.AsyncResponse) { cmdName += "Complete"; } string annotation = Helpers.WrapText(AsSummary(req.Comment)) + eol; var reqFields = new StructField[0]; if (gen != CommandFlavor.AsyncResponse) { reqFields = req.NonTagFields; foreach (var f in reqFields) { annotation += GetParamComment(f) + eol; } } WriteComment(annotation + (GetReturnComment(resp.NonTagFields)), false); string returnType = GetCommandReturnType(gen, resp, cmdName, out string returnFieldName); if (reqFields.Length > 1) { Write(returnType + " " + cmdName); TabIn("("); if (gen != CommandFlavor.AsyncResponse) { foreach (var f in reqFields) { Write(CtorParamTypeFor(f) + " " + f.Name + Separator(f, reqFields, ", ")); } } TabOut(");"); Write(""); } else { string param = reqFields.Length == 1 ? CtorParamTypeFor(reqFields[0]) + " " + reqFields[0].Name : ""; Write($"{returnType} {cmdName}({param});"); } } // GenCommand()
} // GetFieldsDeserializationOps() public void GenMarshalingMethod(bool dirTo, TpmStruct s, bool genPrototype = false, bool serialization = false) { var fields = serialization ? s.NonSizeFields : s.MarshalFields; if (s.DerivedFrom != null || fields.Count() == 0) { return; } string dir = serialization ? dirTo ? "Ser" : "Deser" : dirTo ? "to" : "initFrom", cst = dirTo ? " const" : "", qual = genPrototype ? "" : s.Name + "::", protoAnchor = serialization ? "ialize(Serializer& buf)" : "Tpm(TpmBuffer& buf)", proto = $"void {qual}{dir}{protoAnchor}{cst}"; if (genPrototype) { Write($"{proto};"); return; } var marshalOps = serialization ? dirTo ? GetFieldsSerializationOps(fields) : GetFieldsDeserializationOps(fields) : dirTo?GetToTpmFieldsMarshalOps(fields) : GetFromTpmFieldsMarshalOps(fields); Write(""); if (marshalOps.Count == 1) { // Lay it out in a single line Write($"{proto} {{ {marshalOps[0]}; }}"); } else { Write(proto); TabIn("{"); foreach (var marshalOp in marshalOps) { Write($"{marshalOp};"); } TabOut("}"); } } // GenMarshalingMethod()
public static void AddDerivedStruct(TpmStruct baseStruct, UnionMember curMember, TpmUnion curUnion, string comment = null) { string baseTypeName = baseStruct.SpecName; string newTypeName = baseTypeName + "_" + RemoveEnumPrefix(curMember.SelectorValue.SpecName, curMember.SelectorValue.EnclosingEnum.SpecName); if (!TpmTypes.Contains(newTypeName)) { var newStruct = new TpmStruct(newTypeName, comment ?? "Auto-derived from " + baseTypeName, baseStruct); TpmTypes.Add(newStruct); } var s = (TpmStruct)TpmTypes.Lookup(newTypeName); s.RegisterContainingUnion(curUnion); // Fix up the union field curMember.Type = s; }
/// <summary> Adds fundamental type definitions and a couple of custom classes </summary> internal static void Init() { foreach (var et in TargetLang.GetElementaryTypes()) { Add(et); } TpmStruct s = new TpmStruct("TPM_HANDLE", "Handle of a loaded TPM key or other object [TSS]", null, null, true); s.Add(new StructField("UINT32", "handle", "Handle value")); s.UnderlyingType = Lookup("UINT32"); Add(s); // Create and register empty structs for unions string descr = "Base class for empty union elements.\n" + "An empty union element does not contain any data to marshal.\n" + "This data structure can be used in place of any other union\n" + "initialized with its own empty element."; EmptyUnionBase = new TpmStruct(EmptyUnionBaseName, descr); Add(EmptyUnionBase); }
void GenMarshalingMethod(bool dirTo, TpmStruct s) { var fields = s.MarshalFields; if (s.DerivedFrom != null || fields.Count() == 0) { return; } string dir = dirTo ? "to" : "initFrom", proto = $"def {dir}Tpm({This}, buf):"; var marshalOps = dirTo ? GetToTpmFieldsMarshalOps(fields) : GetFromTpmFieldsMarshalOps(fields); Write(""); TabIn(proto); WriteComment("TpmMarshaller method"); foreach (var op in marshalOps) { Write($"{op}"); } TabOut("", false); } // GenMarshalingMethod()
public UnionMember GetElementOfType(TpmStruct s) { // First look for the exact type match ... foreach (UnionMember m in Members) { if (m.Type.SpecName == s.SpecName) { return(m); } } // ... then see if we have a matching typedef or derived type foreach (UnionMember m in Members) { if (m.Type is TpmTypedef) { TpmType underlyingType = m.Type.StripTypedefs(); if (underlyingType.SpecName == s.SpecName) { return(m); } } else if (m.Type is TpmStruct) { TpmStruct b = (m.Type as TpmStruct).DerivedFrom; while (b != null) { if (b.SpecName == s.SpecName) { return(m); } b = b.DerivedFrom; } } } return(null); }
void GenCommand(TpmStruct req) { var resp = GetRespStruct(req); var cmdName = GetCommandName(req); string respType = resp.Name; string cmdCode = "TPM_CC." + cmdName; var reqFields = req.NonTagFields; var respFields = resp.NonTagFields; if (ForceJustOneReturnParm.Contains(cmdName)) { respFields = respFields.Take(1).ToArray(); } int numOutParms = respFields.Count(); string returnType = numOutParms == 1 ? respFields[0].TypeName : numOutParms == 0 ? "void" : respType; // javadoc annotation string annotation = req.Comment; if (reqFields.Count() != 0) { annotation += eol + eol + "Args:"; foreach (var f in reqFields) { annotation += eol + GetParamComment(f, " ", " "); } } if (respFields.Count() != 0) { annotation += eol + eol + "Returns:"; annotation += eol + GetReturnComment(respFields); } // method definition string paramList = This; string reqStructInitList = ""; foreach (var f in reqFields) { paramList += ", " + f.Name; // ": " + f.TypeName + ", "; reqStructInitList += (reqStructInitList.Length == 0 ? "" : ", ") + f.Name; } TabIn($"def {cmdName}({paramList}):"); WriteComment(annotation); Write($"req = {req.Name}({reqStructInitList})"); Write($"respBuf = {ThisMember}dispatchCommand({cmdCode}, req)"); respType = numOutParms > 0 ? ", " + respType : ""; if (numOutParms == 1) { Write($"res = {ThisMember}processResponse(respBuf{respType})"); Write($"return res.{respFields[0].Name} if res else None"); } else { Write($"return {ThisMember}processResponse(respBuf{respType})"); } TabOut(); Write($"# {cmdName}()"); Write(""); } // GenCommand()
} // GenMarshalingMethod() /// <summary> /// Structures in C are classes in TypeScript /// </summary> /// <param name="s"></param> void GenStruct(TpmStruct s) { bool hasBase = s.DerivedFrom != null; string className = s.Name; string classBases = hasBase ? s.DerivedFrom.Name : !s.IsCmdStruct() ? "TpmStructure" : s.Info.IsRequest() ? "ReqStructure" : "RespStructure"; // If this struct is not derived from another one and is a member of one or more unions, // it must implement the corresponding union interfaces if (!s.IsCmdStruct() && !hasBase) { string unionInterfaces = string.Join(", ", s.ContainingUnions.Select(u => u.Name)); if (unionInterfaces != "") { classBases += ", " + unionInterfaces; } } // Class header TabIn($"class {className} ({classBases}):"); // Javadoc comment for the data structure string annotation = s.Comment + eol; var fields = s.FieldHolder.NonTagFields; if (fields.Length != 0) { annotation += eol + "Attributes:" + eol; foreach (var f in fields) { annotation += GetParamComment(f, " ", " ") + eol; } } // // Field defining constructor // if (fields.Count() == 0) { TabIn($"def __init__({This}):"); WriteComment(annotation); Write("pass"); TabOut(); } else { string ctorParams = string.Join(", ", fields.Select(f => f.Name + $" = {f.GetInitVal()}")); TabIn($"def __init__({This}, {ctorParams}):"); WriteComment(annotation); // If a non-trivial base class is present, all member fields are contained there, // so just pass through the initialization parameters if (hasBase) { string baseInitParams = string.Join(", ", fields.Select(f => f.Name)); //Write($"{s.DerivedFrom}.__init__({baseInitParams})"); Write($"super({className}, {This}).__init__({baseInitParams})"); } else { foreach (var f in fields) { Write($"{ThisMember}{f.Name} = {f.Name}"); } } TabOut(); // // Named union tag getters (instead of the corresponding fields in the TPM 2.0 spec) // foreach (var sel in s.TagFields) { if (sel.MarshalType != MarshalType.UnionSelector) { continue; } var unionField = sel.RelatedUnion; var u = (TpmUnion)unionField.Type; Write(""); Write("@property"); TabIn($"def {sel.Name}({This}): # {sel.TypeName}"); WriteComment(sel.Comment); if (u.NullSelector == null) { Write($"return {unionField.Name}.GetUnionSelector()"); } else { Write($"return {unionField.Name}.GetUnionSelector() if {unionField.Name}" + $" else {u.NullSelector.QualifiedName}"); } TabOut(); } foreach (var f in fields) { if (f.MarshalType != MarshalType.UnionObject) { continue; } var u = (TpmUnion)f.Type; var sel = (f as UnionField).UnionSelector; } } GenGetUnionSelector(s); // // Marshaling // GenMarshalingMethod(true, s); GenMarshalingMethod(false, s); Write(""); Write($"@staticmethod"); TabIn("def fromTpm(buf):"); WriteComment($"Returns new {className} object constructed from its marshaled representation in the given TpmBuffer buffer"); Write($"return buf.createObj({className})"); TabOut(""); Write($"@staticmethod"); TabIn("def fromBytes(buffer):"); WriteComment($"Returns new {className} object constructed from its marshaled representation in the given byte buffer"); Write($"return TpmBuffer(buffer).createObj({className})"); TabOut(); var info = s.IsCmdStruct() ? s.Info as CmdStructInfo : null; if (info != null && (info.NumHandles != 0 || info.SessEncSizeLen != 0)) { if (info.NumHandles != 0) { Write(""); Write($"def numHandles({This}): return {info.NumHandles}"); if (info.IsRequest()) { string handles = string.Join(", ", s.Fields.Take(info.NumHandles).Select(f => ThisMember + f.Name)); Write(""); Write($"def numAuthHandles({This}): return {info.NumAuthHandles}"); Write(""); Write($"def getHandles({This}): return [{handles}]"); } else { Debug.Assert(info.NumHandles == 1 && info.NumAuthHandles == 0); Write(""); Write($"def getHandle({This}): return {ThisMember}{s.Fields[0].Name}"); Write(""); Write($"def setHandle({This}, h): {ThisMember}{s.Fields[0].Name} = h"); } } if (info.SessEncSizeLen != 0) { Debug.Assert(info.SessEncValLen != 0); Write(""); Write($"def sessEncInfo({This}): return SessEncInfo({info.SessEncSizeLen}, {info.SessEncValLen})"); } } // // Custom members // InsertSnip(s.Name); TabOut($"# {className}"); } // GenStruct()
} // GenMarshalingMethod() void GenStruct(TpmStruct s) { bool hasBase = s.DerivedFrom != null; string className = s.Name; string classBases = hasBase ? s.DerivedFrom.Name : !s.IsCmdStruct() ? "TpmStructure" : s.Info.IsRequest() ? "ReqStructure" : "RespStructure"; // If this struct is not derived from another one and is a member of one or more unions, // it must implement the corresponding union interfaces if (!s.IsCmdStruct() && !hasBase) { string unionInterfaces = string.Join(", ", s.ContainingUnions.Select(u => u.Name)); if (unionInterfaces != "") { classBases += " implements " + unionInterfaces; } } // Javadoc comment for the data structure WriteComment(s); // Class header Write($"public class {className} extends {classBases}"); TabIn("{"); // // Fields // Debug.Assert(s.Fields.Count == 0 || !hasBase); foreach (var f in s.NonSizeFields) { if (f.MarshalType == MarshalType.ConstantValue) { continue; } WriteComment(f); if (f.MarshalType == MarshalType.UnionSelector) { var unionField = f.RelatedUnion; var u = (TpmUnion)unionField.Type; Write($"public {f.TypeName} {f.Name}() {{ ", false); if (u.NullSelector == null) { Write($"return {unionField.Name}.GetUnionSelector(); }}"); } else { Write($"return {unionField.Name} != null ? {unionField.Name}.GetUnionSelector()" + $" : {u.NullSelector.QualifiedName}; }}"); } } else { Write($"public {f.TypeName} {f.Name};"); } } // // Default constructor // var fieldsToInit = s.NonDefaultInitFields; Write(""); Write($"public {className}()", false); if (fieldsToInit.Count() == 0) { Write(" {}"); } else if (fieldsToInit.Count() == 1) { var f = fieldsToInit[0]; Write($" {{ {f.Name} = {f.GetInitVal()}; }}"); } else { TabIn("{"); foreach (StructField f in fieldsToInit) { Write($"{f.Name} = {f.GetInitVal()};"); } TabOut("}"); } // // Member-wise constructor // var ctorParams = s.FieldHolder.NonTagFields; if (!s.Info.IsResponse() && ctorParams.Count() != 0) { // Javadoc comments (note that we provide a bit more info for union parameters) string javaDocComment = ""; foreach (var p in ctorParams) { javaDocComment += GetParamComment(p, "_") + eol; } WriteComment(javaDocComment); string ctorOpen = $"public {className}("; string ctorParamList = string.Join(", ", ctorParams.Select(p => p.TypeName + " _" + p.Name)); Write(ctorOpen + ctorParamList + ")", false); if (hasBase) { if (ctorParams.Length == 1) { Write($" {{ super(_{ctorParams[0].Name}); }}"); } else { string ctorParamNamesList = string.Join(", ", ctorParams.Select(p => "_" + p.Name)); TabIn("{"); Write($"super({ctorParamNamesList});"); TabOut("}"); } } else if (ctorParams.Length == 1) { var p = ctorParams[0]; Write($" {{ {p.Name} = _{p.Name}; }}"); } else { TabIn("{"); foreach (var p in ctorParams) { // We turn shorts into ints in constructor args, to allow external API users // avoid incessant casting. Instead the cast is hidden in the constructor body. // Note that we cannot change the type of the corresponding members, as it is // dictated by the TPM 2.0 spec. Write($"{p.Name} = _{p.Name};"); } TabOut("}"); } } // // Union interface: TpmUnion.GetUnionSelector() // GenGetUnionSelector(s); // // Marshaling // GenMarshalingMethod(true, s); GenMarshalingMethod(false, s); WriteComment("@deprecated Use {@link #toBytes()} instead\n" + "@return Wire (marshaled) representation of this object"); Write("public byte[] toTpm () { return toBytes(); }"); WriteComment("Static marshaling helper\n" + "@param byteBuf Wire representation of the object\n" + "@return New object constructed from its wire representation"); Write($"public static {className} fromBytes (byte[] byteBuf) "); TabIn("{"); Write($"return new TpmBuffer(byteBuf).createObj({className}.class);"); TabOut("}"); WriteComment("@deprecated Use {@link #fromBytes(byte[])} instead\n" + "@param byteBuf Wire representation of the object\n" + "@return New object constructed from its wire representation"); Write($"public static {className} fromTpm (byte[] byteBuf) {{ return fromBytes(byteBuf); }}"); WriteComment("Static marshaling helper\n" + "@param buf Wire representation of the object\n" + "@return New object constructed from its wire representation"); Write($"public static {className} fromTpm (TpmBuffer buf) "); TabIn("{"); Write($"return buf.createObj({className}.class);"); TabOut("}"); Write("@Override"); Write("public String toString()"); TabIn("{"); Write($"TpmStructurePrinter _p = new TpmStructurePrinter(\"{s.Name}\");"); Write("toStringInternal(_p, 1);"); Write("_p.endStruct();"); Write("return _p.toString();"); TabOut("}", false); if (s.Fields.Count() > 0) { Write("@Override"); Write("public void toStringInternal(TpmStructurePrinter _p, int d)"); TabIn("{"); foreach (StructField f in ctorParams) { Write($"_p.add(d, \"{f.TypeName}\", \"{f.Name}\", {f.Name});"); } TabOut("}", false); } var info = s.IsCmdStruct() ? s.Info as CmdStructInfo : null; if (info != null && (info.NumHandles != 0 || info.SessEncSizeLen != 0)) { if (info.NumHandles != 0) { Write("@Override"); Write($"public int numHandles() {{ return {info.NumHandles}; }}"); if (info.IsRequest()) { string handles = string.Join(", ", s.Fields.Take(info.NumHandles).Select(f => ThisMember + f.Name)); Write("@Override"); Write($"public int numAuthHandles() {{ return {info.NumAuthHandles}; }}"); Write("@Override"); Write($"public TPM_HANDLE[] getHandles() {{ return new TPM_HANDLE[] {{{handles}}}; }}"); } else { Debug.Assert(info.NumHandles == 1 && info.NumAuthHandles == 0); Write("@Override"); Write($"public TPM_HANDLE getHandle() {{ return {ThisMember}{s.Fields[0].Name}; }}"); Write("@Override"); Write($"public void setHandle(TPM_HANDLE h) {{ {ThisMember}{s.Fields[0].Name} = h; }}"); } } if (info.SessEncSizeLen != 0) { Debug.Assert(info.SessEncValLen != 0); Write("@Override"); Write($"public SessEncInfo sessEncInfo() {{ return new SessEncInfo({info.SessEncSizeLen}, {info.SessEncValLen}); }}"); } } InsertSnip(s.Name); TabOut("}", false); } // GenStruct()
} // GenCommands() void GenCommand(TpmStruct req) { var resp = GetRespStruct(req); var cmdName = GetCommandName(req); string respType = resp.Name; string cmdCode = "TPM_CC." + cmdName; var fields = req.NonTagFields; var respFields = resp.NonTagFields; if (ForceJustOneReturnParm.Contains(cmdName)) { respFields = respFields.Take(1).ToArray(); } int numOutParms = respFields.Count(); string returnType = numOutParms == 1 ? respFields[0].TypeName : numOutParms == 0 ? "void" : respType; // javadoc annotation string annotation = req.Comment + eol + eol; foreach (var f in fields) { annotation += GetParamComment(f) + eol; } annotation += GetReturnComment(respFields); WriteComment(annotation); // method definition string paramList = ""; string reqStructInitList = ""; foreach (var f in fields) { string comma = Separator(f, fields, ", "); paramList += f.TypeName + " " + f.Name + comma; reqStructInitList += f.Name + comma; } Write($"public {returnType} {cmdName}({paramList})"); TabIn("{"); Write($"{req.Name} req = new {req.Name}({reqStructInitList});"); string outParm = "null"; if (numOutParms != 0) { Write($"{respType} resp = new {respType}();"); outParm = "resp"; } Write($"DispatchCommand({cmdCode}, req, {outParm});"); if (numOutParms == 0) { Write("return;"); } else if (numOutParms == 1) { Write("return resp." + respFields[0].Name + ";"); } else { Write("return resp;"); } TabOut("}"); } // GenCommand()
internal static string GetCommandName(TpmStruct req) { return(req.SpecName.Replace("TPM2_", "").Replace("_REQUEST", "")); }
// The spec uses these two sorts of tagged structure commonly // { len, array[len] } and // { selector, [select]union } // This routine changes references to these sorts of structure to an embedded form. public static void FlattenTaggedStructures() { // Build the list of tagged structures List <TpmStruct> taggedStructs = new List <TpmStruct>(); foreach (TpmType tp in TpmTypes.TheTypes) { var s = tp as TpmStruct; if (s == null) { continue; } var t = s; while (t != null && t.Fields.Count != 2) { t = t.DerivedFrom; } if (t == null || s.SpecName.IsOneOf(DontFlatten)) { continue; } if ((t.Fields[0].MarshalType == MarshalType.ArrayCount) || (t.Fields[0].MarshalType == MarshalType.UnionSelector) || (t.Fields[0].MarshalType == MarshalType.LengthOfStruct) ) { taggedStructs.Add(s); } } // find references to the tagged structures and replace them foreach (TpmType tp in TpmTypes.TheTypes) { if (!(tp is TpmStruct)) { continue; } TpmStruct t = (TpmStruct)tp; for (int j = 0; j < t.Fields.Count; j++) { StructField origField = t.Fields[j]; if (origField.IsArray()) { continue; // Don't flatten arrays } var toEmbed = origField.Type as TpmStruct; if (taggedStructs.Contains(toEmbed)) { // If a structure to flatten is one without fields of its own, // but is derived from a flattenable one, unwind the inheritance chain. while (toEmbed != null && toEmbed.Fields.Count != 2) { toEmbed = toEmbed.DerivedFrom; } StructField tagToEmbed = toEmbed.Fields[0]; Debug.Assert(origField.MinVal == null || origField.MinVal == tagToEmbed.MinVal); Debug.Assert(origField.MaxVal == null || origField.MaxVal == tagToEmbed.MaxVal); var bufToEmbed = toEmbed.Fields[1]; string newTagName = origField.Name + Helpers.Capitalize(tagToEmbed.Name); string newBufTypeName = bufToEmbed.Type.SpecName; var newTagField = new StructField(tagToEmbed, newTagName); t.Fields[j] = newTagField; switch (tagToEmbed.MarshalType) { case MarshalType.UnionSelector: { var newField = new UnionField(newBufTypeName, origField.Name, origField.Comment, newTagName, t); t.Fields.Insert(j + 1, newField); break; } case MarshalType.ArrayCount: { var newField = new VariableLengthArray(newBufTypeName, origField.Name, origField.Comment, newTagName, t); t.Fields.Insert(j + 1, newField); break; } case MarshalType.LengthOfStruct: { var newField = new StructField(newBufTypeName, origField.Name, origField.Comment); t.Fields.Insert(j + 1, newField); newTagField.MarshalType = MarshalType.LengthOfStruct; newTagField.SizedField = newField; newField.MarshalType = MarshalType.SizedStruct; newField.SizeTagField = newTagField; break; } default: throw new Exception(""); } } // j-loop } } }
internal static TpmStruct GetRespStruct(TpmStruct req) { return((TpmStruct)TpmTypes.Lookup(req.SpecName.Replace("_REQUEST", "Response").Substring(5))); }
void GenStructDecl(TpmStruct s) { bool hasBase = s.DerivedFrom != null; // Has a non-trivial base class? string className = s.Name; if (IsTypedefStruct(s)) { Debug.Assert(s.Fields.Count == 0); WriteComment(s); Write($"typedef {s.DerivedFrom.Name} {className};"); Write(""); return; } string classBases = hasBase ? s.DerivedFrom.Name : !s.IsCmdStruct() ? "TpmStructure" : s.Info.IsRequest() ? "ReqStructure" : "RespStructure"; string virt = ""; // If this struct is not derived from another one and is a member of one or more unions, // it must implement the corresponding union interfaces if (!s.IsCmdStruct() && !hasBase && s.ContainingUnions.Count > 0) { foreach (var u in s.ContainingUnions) { classBases += ", public " + u.Name; } virt = "virtual "; } WriteComment(s); Write($"class _DLLEXP_ {className} : public {virt}{classBases}"); Write("{"); TabIn("public:"); // // Fields // TpmField conversionSource = null; foreach (var f in s.NonSizeFields) { if (f.MarshalType == MarshalType.ConstantValue) { // No member field for a constant tag continue; } WriteComment(f); if (f.MarshalType == MarshalType.UnionSelector) { var unionField = f.RelatedUnion; var u = (TpmUnion)unionField.Type; Write($"public: {f.TypeName} {f.Name}() const {{ ", false); if (u.NullSelector == null) { Write($"return {unionField.Name}->GetUnionSelector(); }}"); } else { Write($"return {unionField.Name} ? {unionField.Name}->GetUnionSelector()" + $" : {u.NullSelector.QualifiedName}; }}"); } continue; } Write($"{TransType(f)} {f.Name};"); } TabOut(""); TabIn("public:"); // // Default constructor // var fieldsToInit = s.NonDefaultInitFields; Write($"{className}()", false); if (fieldsToInit.Count() == 0) { Write(" {}"); } else if (fieldsToInit.Count() == 1) { Write($" {{ {fieldsToInit[0].Name} = {fieldsToInit[0].GetInitVal()}; }}"); } else { TabIn("{"); foreach (StructField f in fieldsToInit) { Write($"{f.Name} = {f.GetInitVal()};"); } TabOut("}"); } // // Member-wise constructor // var ctorParams = s.FieldHolder.NonTagFields; if (!s.Info.IsResponse() && ctorParams.Count() != 0) { string baseClass = hasBase ? s.DerivedFrom.Name : "TpmStructure"; string ctorParamList = string.Join(", ", ctorParams.Select(p => $"{CtorParamTypeFor(p)} _{p.Name}")); Write($"{className}({ctorParamList})"); if (hasBase) { string ctorParamNamesList = string.Join(", ", ctorParams.Select(p => "_" + p.Name)); Write($" : {baseClass}({ctorParamNamesList})"); } else { string memInitList = string.Join(", ", ctorParams.Select(p => p.Type is TpmUnion ? $"{p.Name}(dynamic_cast<{p.Type.Name}*>(_{p.Name}.Clone()))" : $"{p.Name}(_{p.Name})" )); Write($" : {memInitList}"); } Write("{}"); } if (conversionSource != null) { Write(""); Write($"operator ByteVec&() {{ return {conversionSource.Name}; }}"); Write($"operator const ByteVec&() const {{ return {conversionSource.Name}; }}"); } // // Union interface: TpmUnion.GetUnionSelector() // GenGetUnionSelector(s); // // Marshaling // Write(""); GenMarshalingMethod(true, s, true); GenMarshalingMethod(false, s, true); string comment = AsSummary("Static marshaling helper"); WriteComment(comment); Write($"static {className} fromTpm(TpmBuffer& buf) {{ return buf.createObj<{className}>(); }}"); WriteComment(comment); Write($"static {className} fromBytes(const ByteVec& buf) {{ return TpmStructure::fromBytes<{className}>(buf); }}"); // // Serialization // Write(""); Write($"virtual const char* TypeName () const {{ return \"{className}\"; }}"); Write(""); Write("using TpmStructure::Serialize;"); Write("using TpmStructure::Deserialize;"); GenMarshalingMethod(true, s, true, true); GenMarshalingMethod(false, s, true, true); // // Cloning and metadata // Write(""); Write($"virtual TpmStructure* Clone() const {{ return new {className}(*this); }}"); var info = s.IsCmdStruct() ? s.Info as CmdStructInfo : null; if (info != null && (info.NumHandles != 0 || info.SessEncSizeLen != 0)) { TabOut(""); TabIn("protected:"); if (info.NumHandles != 0) { Write($"virtual uint16_t numHandles() const {{ return {info.NumHandles}; }}"); if (info.IsRequest()) { string handles = string.Join(", ", s.Fields.Take(info.NumHandles).Select(f => f.Name)); Write($"virtual uint16_t numAuthHandles() const {{ return {info.NumAuthHandles}; }}"); Write($"virtual vector<TPM_HANDLE> getHandles() const {{ return {{{handles}}}; }}"); } else { Debug.Assert(info.NumHandles == 1 && info.NumAuthHandles == 0); Write($"virtual TPM_HANDLE getHandle() const {{ return {s.Fields[0].Name}; }}"); Write($"virtual void setHandle(const TPM_HANDLE& h) {{ {s.Fields[0].Name} = h; }}"); } } if (info.SessEncSizeLen != 0) { Debug.Assert(info.SessEncValLen != 0); Write(""); Write($"virtual SessEncInfo sessEncInfo() const {{ return {{{info.SessEncSizeLen}, {info.SessEncValLen}}}; }}"); } } InsertSnip(s.Name); TabOut($"}}; // class {className}"); } // GenStruct()
/// <summary> Determines whether this struct is represented as a typedef in C++ </summary> static bool IsTypedefStruct(TpmStruct s) { return(s.DerivedFrom != null && s.ContainingUnions.Count == 0); }
} // GenCommandDispatchers() void GenCommandDispatcher(TpmStruct req, CommandFlavor gen) { var resp = GetRespStruct(req); string cmdName = GetCommandName(req); string cmdCode = "TPM_CC::" + cmdName; string inStructId = req.Name + "_ID"; string outStructId = resp.Name + "_ID"; switch (gen) { case CommandFlavor.AsyncCommand: cmdName += ""; break; case CommandFlavor.AsyncResponse: cmdName += "Complete"; break; default: break; } string returnFieldName; string returnType = GetCommandReturnType(gen, resp, cmdName, out returnFieldName); string className = " Tpm2::" + (gen != CommandFlavor.Synch ? "AsyncMethods::" : ""); bool paramsPresent = gen != CommandFlavor.AsyncResponse; var cmdParamFields = paramsPresent ? req.NonTagFields : new StructField[0]; bool multiline = cmdParamFields.Count() > 1; StructField lastParm = cmdParamFields.Count() > 0 ? lastParm = cmdParamFields.Last() : null; Write(returnType + className + cmdName + "(" + (cmdParamFields.Count() == 0 ? ")" : (multiline ? "" : CtorParamTypeFor(cmdParamFields[0]) + " " + cmdParamFields[0].Name + ")"))); if (multiline) { TabIn(); foreach (var f in cmdParamFields) { Write(CtorParamTypeFor(f) + " " + f.Name + (f == lastParm ? ")" : ", ")); } TabOut(); } TabIn("{"); string reqParams = ""; if (paramsPresent && req.Fields.Count() != 0) { string ctorInitList = string.Join(", ", cmdParamFields.Select(f => f.Name)); Write($"{req.Name} req({ctorInitList});"); reqParams = ", req"; } string respParam = ""; if (returnType != "void") { Debug.Assert(resp.Fields.Count() != 0); Write($"{resp.Name} resp;"); respParam = ", resp"; } string dispatchCall = gen == CommandFlavor.AsyncCommand ? "theTpm.DispatchOut" : gen == CommandFlavor.AsyncResponse ? "theTpm.DispatchIn" : "Dispatch"; Write(dispatchCall + $"({cmdCode}{reqParams}{respParam});"); if (gen != CommandFlavor.AsyncCommand) { if (returnFieldName != null) { Write($"return resp.{returnFieldName};"); } else if (returnType != "void") { Write("return resp;"); } } TabOut("}"); } // GenCommandDispatcher()
} // GenCommands() void GenCommand(TpmStruct req) { const string NS = "tt."; var resp = GetRespStruct(req); var cmdName = GetCommandName(req); string respType = NS + resp.Name; string cmdCode = NS + "TPM_CC." + cmdName; var fields = req.NonTagFields; var respFields = resp.NonTagFields; if (ForceJustOneReturnParm.Contains(cmdName)) { respFields = respFields.Take(1).ToArray(); } int numOutParms = respFields.Count(); string returnType = numOutParms == 1 ? NsQualifiedType(respFields[0], NS) : numOutParms == 0 ? "void" : respType; // javadoc annotation string annotation = req.Comment + eol + eol; foreach (var f in fields) { annotation += GetParamComment(f) + eol; } annotation += GetReturnComment(respFields); WriteComment(annotation); // method definition string paramList = ""; string reqStructInitList = ""; foreach (var f in fields) { string parmTypeName = NsQualifiedType(f, NS); string comma = Separator(f, fields, ", "); paramList += f.Name + ": " + parmTypeName + ", "; reqStructInitList += f.Name + comma; } var indent = new string(' ', cmdName.Length + 2); string respParams = returnType == null ? "" : "res?: " + returnType; if (paramList != "") { Write($"{cmdName}({paramList}"); Write($"{indent}continuation: (err: TpmError, {respParams}) => void)"); } else { Write($"{cmdName}(continuation: (err: TpmError, {respParams}) => void)"); } Write("{"); TabIn(); Write($"let req = new {NS}{req.Name}({reqStructInitList});"); Write($"{ThisMember}dispatchCommand({cmdCode}, req, (respBuf: TpmBuffer): void => {{"); respType = numOutParms > 0 ? ", " + respType : ""; Write($"let res = {ThisMember}processResponse(respBuf{respType});"); string res = "", resField = ""; if (numOutParms > 0) { res = ", res"; if (numOutParms == 1) { resField = $"?.{respFields[0].Name}"; } } Write($"setImmediate(continuation, {ThisMember}lastError{res}{resField}); }});"); TabOut($"}} // {cmdName}()"); } // GenCommand()
} // GenMarshalingMethod() /// <summary> /// Structures in C are classes in TypeScript /// </summary> /// <param name="s"></param> void GenStruct(TpmStruct s) { bool hasBase = s.DerivedFrom != null; string className = s.Name; string classBases = hasBase ? s.DerivedFrom.Name : !s.IsCmdStruct() ? "TpmStructure" : s.Info.IsRequest() ? "ReqStructure" : "RespStructure"; // If this struct is not derived from another one and is a member of one or more unions, // it must implement the corresponding union interfaces if (!s.IsCmdStruct() && !hasBase) { string unionInterfaces = string.Join(", ", s.ContainingUnions.Select(u => u.Name)); if (unionInterfaces != "") { classBases += " implements " + unionInterfaces; } } // Javadoc comment for the data structure WriteComment(s); // Class header Write($"export class {className} extends {classBases}"); TabIn("{"); // In TypeScript, member fields declaration is melded with member-wise constructor // that also playe the role of the default one // // Field defining constructor // var fields = s.FieldHolder.NonTagFields; if (fields.Count() == 0) { Write("constructor() { super(); }"); } else { Write("constructor("); TabIn(); // If a non-trivial base class is present, all member fields are contained there, // so just pass through the initialization parameters string ctrParamQualifier = hasBase ? "" : "public "; string baseIntializers = ""; foreach (var f in fields) { // Javadoc comment for the member/constructor parameter. // Add a list of data structures implementing the interface of a union parameters. WriteComment(f); string comma = Separator(f, fields, ", "); Write($"{ctrParamQualifier}{f.Name}: {f.TypeName} = {f.GetInitVal()}{comma}"); if (hasBase) { baseIntializers += f.Name + comma; } } TabOut($") {{ super({baseIntializers}); }}"); // // Named union tag getters (instead of the corresponding fields in the TPM 2.0 spec) // foreach (var sel in s.TagFields) { if (sel.MarshalType != MarshalType.UnionSelector) { continue; } var u = (TpmUnion)sel.RelatedUnion.Type; string unionField = ThisMember + sel.RelatedUnion.Name; WriteComment(sel); Write($"get {sel.Name}(): {sel.TypeName} {{ ", false); if (u.NullSelector == null) { Write($"return {unionField}.GetUnionSelector(); }}"); } else { Write($"return {unionField} ? {unionField}.GetUnionSelector()" + $" : {u.NullSelector.QualifiedName}; }}"); } } } // // Union interface: TpmUnion.GetUnionSelector() // GenGetUnionSelector(s); // // Marshaling // GenMarshalingMethod(true, s); GenMarshalingMethod(false, s); WriteComment("Static marshaling helper"); Write($"public static fromTpm(buf: TpmBuffer) : {className}"); TabIn("{"); Write($"return buf.createObj({className});"); TabOut("}"); WriteComment("Static marshaling helper"); Write($"public static fromBytes(buffer: any) : {className}"); TabIn("{"); Write($"return new TpmBuffer(buffer).createObj({className});"); TabOut("}"); var info = s.IsCmdStruct() ? s.Info as CmdStructInfo : null; if (info != null && (info.NumHandles != 0 || info.SessEncSizeLen != 0)) { if (info.NumHandles != 0) { Write($"numHandles(): number {{ return {info.NumHandles}; }}"); if (info.IsRequest()) { string handles = string.Join(", ", s.Fields.Take(info.NumHandles).Select(f => ThisMember + f.Name)); Write($"numAuthHandles(): number {{ return {info.NumAuthHandles}; }}"); Write($"getHandles(): TPM_HANDLE[] {{ return [{handles}]; }}"); } else { Debug.Assert(info.NumHandles == 1 && info.NumAuthHandles == 0); Write($"getHandle(): TPM_HANDLE {{ return {ThisMember}{s.Fields[0].Name}; }}"); Write($"setHandle(h: TPM_HANDLE): void {{ {ThisMember}{s.Fields[0].Name} = h; }}"); } } if (info.SessEncSizeLen != 0) { Debug.Assert(info.SessEncValLen != 0); Write(""); Write($"sessEncInfo(): SessEncInfo {{ return new SessEncInfo({info.SessEncSizeLen}, {info.SessEncValLen}); }}"); } } // // Custom members // InsertSnip(s.Name); TabOut($"}} // {className}"); } // GenStruct()