@@ -329,20 +329,22 @@ def _parse_fields(self, xmlfields: ET.Element, reg: _TPMIRegisterTypedDict):
329329 field ["readonly" ] = xmlfield .attrib ["AccessType" ].lower () != "rw"
330330
331331 for xmldata in xmlfield :
332- if xmldata .tag == "LongDescription" :
333- for desc_data in xmldata :
334- if desc_data .tag != "Text" :
335- raise Error (f"Unexpected XML element tag '{ desc_data .tag } ' "
336- f"in LongDescription of field '{ name } ' of TPMI register "
337- f"'{ regname } ' in XML file '{ self ._xml_paths ['regs' ]} '" )
338- if desc_data .text :
339- desc = desc_data .text .strip ()
340- # Remove newlines and multiple spaces/tabs.
341- desc = " " .join (desc .split ())
342- if desc .endswith ('.' ):
343- desc = desc [:- 1 ]
344- field ["desc" ] = desc
345- break
332+ if xmldata .tag != "LongDescription" :
333+ continue
334+
335+ for desc_data in xmldata :
336+ if desc_data .tag != "Text" :
337+ raise Error (f"Unexpected XML element tag '{ desc_data .tag } ' in "
338+ f"LongDescription of field '{ name } ' of TPMI register "
339+ f"'{ regname } ' in XML file '{ self ._xml_paths ['regs' ]} '" )
340+ if desc_data .text :
341+ desc = desc_data .text .strip ()
342+ # Remove newlines and multiple spaces/tabs.
343+ desc = " " .join (desc .split ())
344+ if desc .endswith ('.' ):
345+ desc = desc [:- 1 ]
346+ field ["desc" ] = desc
347+ break
346348
347349 if name in reg ["fields" ]:
348350 raise Error (f"Duplicate field '{ name } ' found in TPMI register '{ regname } ' in XML "
@@ -442,6 +444,126 @@ def _get_extension_data(self,
442444 data = Trivial .str_to_int (xmldata .attrib ["Data" ], what = what )
443445 return data
444446
447+ def __parse_instance (self ,
448+ xmlreg : ET .Element ,
449+ instpath : Path ,
450+ feature_names_set : set [str ],
451+ include_intelrsvd : bool = False ,
452+ include_nonos : bool = False ):
453+ """
454+ Implement '_parse_instance()' method, helps avoiding too many nested levels.
455+ """
456+
457+ for attrname in ("Name" , "AddressOffset" , "ValueDataType" ):
458+ if attrname not in xmlreg .attrib :
459+ _LOG .debug ("Missing '%s' attribute in the following XML element:\n %s" ,
460+ attrname , ET .tostring (xmlreg , encoding = 'unicode' ))
461+ raise Error (f"Missing '{ attrname } ' attribute in a 3rd-level 'RegisterInstance' XML "
462+ f"element in XML file '{ instpath } '" )
463+
464+ regname = xmlreg .attrib ["Name" ]
465+ regtype = xmlreg .attrib ["ValueDataType" ]
466+
467+ if "ShortDescription" in xmlreg .attrib :
468+ desc = xmlreg .attrib ["ShortDescription" ].strip ()
469+ # Remove newlines and multiple spaces/tabs.
470+ desc = " " .join (desc .split ())
471+ if desc .endswith ('.' ):
472+ desc = desc [:- 1 ]
473+ else :
474+ desc = ""
475+
476+
477+ feature_id : int = - 1
478+ is_intel_reserved : bool = False
479+
480+ for xmldata in xmlreg :
481+ if xmldata .tag == "LongDescription" :
482+ for desc_data in xmldata :
483+ if desc_data .tag != "Text" :
484+ raise Error (f"Unexpected XML element tag '{ desc_data .tag } ' in "
485+ f"'LongDescription' of TPMI register '{ regname } ' in TPMI "
486+ f"instance file '{ instpath } '" )
487+ if desc_data .text :
488+ desc = desc_data .text .strip ()
489+ # Remove newlines and multiple spaces/tabs.
490+ desc = " " .join (desc .split ())
491+ break
492+
493+ if xmldata .tag == "Extension" :
494+ if xmldata .attrib .get ("Key" , "" ) == "TPMI_ID" :
495+ data = self ._get_extension_data (xmldata , "TPMI_ID" , regname , instpath )
496+ if data is None :
497+ break
498+ feature_id = data
499+ elif xmldata .attrib .get ("Key" , "" ) == "IntelRsvd" :
500+ data = self ._get_extension_data (xmldata , "IntelRsvd" , regname , instpath )
501+ if data :
502+ is_intel_reserved = True
503+ break
504+
505+ if is_intel_reserved and not include_intelrsvd :
506+ _LOG .debug ("TPMI register '%s' in TPMI instance file '%s' is marked as IntelRsvd, "
507+ "skipping it" , regname , instpath )
508+ return
509+
510+ if feature_id == - 1 :
511+ _LOG .debug ("TPMI register '%s' in TPMI instance file '%s' has no TPMI_ID" ,
512+ regname , instpath )
513+ return
514+
515+ # Skip register definition presence verification until after TPMI_ID processing. Registers
516+ # without a valid # TPMI_ID will be filtered out, avoiding unnecessary warnings for
517+ # registers that are intentionally excluded from the registers XML file.
518+ if regtype not in self ._regs :
519+ if "RESERVED" not in regname and "RSVD" not in regname :
520+ _LOG .warning ("TPMI register '%s' referenced in TPMI instance file '%s' is not "
521+ "defined in the TPMI registers XML file '%s'" ,
522+ regname , instpath , self ._xml_paths ["regs" ])
523+ return
524+
525+ if feature_id not in FEATURES_INFO :
526+ _LOG .warning ("Unknown TPMI feature ID %#x for TPMI register '%s' in TPMI instance file "
527+ "'%s'" , feature_id , regname , instpath )
528+ return
529+
530+ if FEATURES_INFO [feature_id ]["name" ] not in feature_names_set :
531+ _LOG .debug ("Skipping TPMI register '%s' in TPMI instance file '%s' because its feature "
532+ "'%s' is not in the include list" ,
533+ regname , instpath , FEATURES_INFO [feature_id ]["name" ])
534+ return
535+
536+ if FEATURES_INFO [feature_id ]["ignore" ] and not include_nonos :
537+ _LOG .debug ("Ignoring TPMI register '%s' in TPMI instance file '%s' because its feature "
538+ "ID %#x is marked as ignored" , regname , instpath , feature_id )
539+ return
540+
541+ addr = Trivial .str_to_int (xmlreg .attrib ["AddressOffset" ],
542+ what = f"Address of TPMI register '{ regname } ' in TPMI instance "
543+ f"file '{ instpath } '" )
544+
545+ fname = FEATURES_INFO [feature_id ]["name" ]
546+
547+ if fname not in self ._features :
548+ feature : _TPMIFeatureTypedDict = {}
549+ feature ["name" ] = fname
550+ feature ["desc" ] = FEATURES_INFO [feature_id ]["desc" ]
551+ feature ["feature_id" ] = feature_id
552+ feature ["registers" ] = {}
553+ self ._features [fname ] = feature
554+
555+ if regname not in self ._features [fname ]["registers" ]:
556+ reg = self ._regs [regtype ].copy ()
557+ if "desc" not in reg and desc :
558+ reg ["desc" ] = desc
559+
560+ # The offset will be adjusted a bit later to become relative to the feature
561+ # base.
562+ reg ["offset" ] = addr
563+ self ._features [fname ]["registers" ][regname ] = reg
564+
565+ _LOG .debug ("Processed TPMI register '%s' in TPMI instance file '%s'" , regname , instpath )
566+
445567 def _parse_instance (self ,
446568 instpath : Path ,
447569 feature_names : Sequence [str ],
@@ -459,7 +581,6 @@ def _parse_instance(self,
459581 """
460582
461583 feature_names_set = set (feature_names )
462-
463584 try :
464585 tree = ET .parse (instpath )
465586 root = tree .getroot ()
@@ -478,118 +599,9 @@ def _parse_instance(self,
478599 raise Error (f"Unexpected 3rd-level XML element tag '{ xmlreg .tag } ' in XML file "
479600 f"'{ instpath } '" )
480601
481- for attrname in ("Name" , "AddressOffset" , "ValueDataType" ):
482- if attrname not in xmlreg .attrib :
483- _LOG .debug ("Missing '%s' attribute in the following XML element:\n %s" ,
484- attrname , ET .tostring (xmlreg , encoding = 'unicode' ))
485- raise Error (f"Missing '{ attrname } ' attribute in a 3rd-level "
486- f"'RegisterInstance' XML element in XML file '{ instpath } '" )
487-
488- regname = xmlreg .attrib ["Name" ]
489- regtype = xmlreg .attrib ["ValueDataType" ]
490-
491- if "ShortDescription" in xmlreg .attrib :
492- desc = xmlreg .attrib ["ShortDescription" ].strip ()
493- # Remove newlines and multiple spaces/tabs.
494- desc = " " .join (desc .split ())
495- if desc .endswith ('.' ):
496- desc = desc [:- 1 ]
497- else :
498- desc = ""
499-
500-
501- feature_id : int = - 1
502- is_intel_reserved : bool = False
503-
504- for xmldata in xmlreg :
505- if xmldata .tag == "LongDescription" :
506- for desc_data in xmldata :
507- if desc_data .tag != "Text" :
508- raise Error (f"Unexpected XML element tag '{ desc_data .tag } ' "
509- f"in 'LongDescription' of TPMI register '{ regname } ' in "
510- f"TPMI instance file '{ instpath } '" )
511- if desc_data .text :
512- desc = desc_data .text .strip ()
513- # Remove newlines and multiple spaces/tabs.
514- desc = " " .join (desc .split ())
515- break
516-
517- if xmldata .tag == "Extension" :
518- if xmldata .attrib .get ("Key" , "" ) == "TPMI_ID" :
519- data = self ._get_extension_data (xmldata , "TPMI_ID" , regname , instpath )
520- if data is None :
521- break
522- feature_id = data
523- elif xmldata .attrib .get ("Key" , "" ) == "IntelRsvd" :
524- data = self ._get_extension_data (xmldata , "IntelRsvd" , regname , instpath )
525- if data :
526- is_intel_reserved = True
527- break
528-
529- if is_intel_reserved and not include_intelrsvd :
530- _LOG .debug ("TPMI register '%s' in TPMI instance file '%s' is marked as "
531- "IntelRsvd, skipping it" , regname , instpath )
532- continue
533-
534- if feature_id == - 1 :
535- _LOG .debug ("TPMI register '%s' in TPMI instance file '%s' has no TPMI_ID" ,
536- regname , instpath )
537- continue
538-
539- # Skip register definition presence verification until after TPMI_ID processing.
540- # Registers without a valid # TPMI_ID will be filtered out, avoiding unnecessary
541- # warnings for registers that are intentionally excluded from the registers XML
542- # file.
543- if regtype not in self ._regs :
544- if "RESERVED" not in regname and "RSVD" not in regname :
545- _LOG .warning ("TPMI register '%s' referenced in TPMI instance file '%s' is "
546- "not defined in the TPMI registers XML file '%s'" ,
547- regname , instpath , self ._xml_paths ["regs" ])
548- continue
549-
550- if feature_id not in FEATURES_INFO :
551- _LOG .warning ("Unknown TPMI feature ID %#x for TPMI register '%s' in TPMI "
552- "instance file '%s'" , feature_id , regname , instpath )
553- continue
554-
555- if FEATURES_INFO [feature_id ]["name" ] not in feature_names_set :
556- _LOG .debug ("Skipping TPMI register '%s' in TPMI instance file '%s' because its "
557- "feature '%s' is not in the include list" , regname , instpath ,
558- FEATURES_INFO [feature_id ]["name" ])
559- continue
560-
561- if FEATURES_INFO [feature_id ]["ignore" ] and not include_nonos :
562- _LOG .debug ("Ignoring TPMI register '%s' in TPMI instance file '%s' because "
563- "its feature ID %#x is marked as ignored" ,
564- regname , instpath , feature_id )
565- continue
566-
567- addr = Trivial .str_to_int (xmlreg .attrib ["AddressOffset" ],
568- what = f"Address of TPMI register '{ regname } ' in TPMI "
569- f"instance file '{ instpath } '" )
570-
571- fname = FEATURES_INFO [feature_id ]["name" ]
572-
573- if fname not in self ._features :
574- feature : _TPMIFeatureTypedDict = {}
575- feature ["name" ] = fname
576- feature ["desc" ] = FEATURES_INFO [feature_id ]["desc" ]
577- feature ["feature_id" ] = feature_id
578- feature ["registers" ] = {}
579- self ._features [fname ] = feature
580-
581- if regname not in self ._features [fname ]["registers" ]:
582- reg = self ._regs [regtype ].copy ()
583- if "desc" not in reg and desc :
584- reg ["desc" ] = desc
585-
586- # The offset will be adjusted a bit later to become relative to the feature
587- # base.
588- reg ["offset" ] = addr
589- self ._features [fname ]["registers" ][regname ] = reg
590-
591- _LOG .debug ("Processed TPMI register '%s' in TPMI instance file '%s'" ,
592- regname , instpath )
602+ self .__parse_instance (xmlreg , instpath , feature_names_set ,
603+ include_intelrsvd = include_intelrsvd ,
604+ include_nonos = include_nonos )
593605
594606 def _parse_instances (self ,
595607 feature_names : Sequence [str ],
0 commit comments