diff --git a/SetupDataPkg/Docs/PlatformIntegration/PlatformIntegrationSteps.md b/SetupDataPkg/Docs/PlatformIntegration/PlatformIntegrationSteps.md index 8f3ea7d4..77ce6c3c 100644 --- a/SetupDataPkg/Docs/PlatformIntegration/PlatformIntegrationSteps.md +++ b/SetupDataPkg/Docs/PlatformIntegration/PlatformIntegrationSteps.md @@ -111,12 +111,29 @@ queries variable storage for any appropriately sized overrides to config knobs. The platform must define `CONF_AUTOGEN_INCLUDE_PATH` in PlatformBuild.py. This is the absolute path that the autogenerated header files will be placed under as such: `CONF_AUTOGEN_INCLUDE_PATH\Generated\Config*.h`. The UpdateConfigHdr.py -build plugin will create the `Generated` directory if it does not exist. +build plugin will create the `Generated` directory if it does not exist. If there are multiple environments being built +in one build, e.g. StandaloneMM and DXE environments with separate config, PlatformBuild.py may put a semicolon +delimited list of include paths here such as: + +```python +self.env.SetValue("CONF_AUTOGEN_INCLUDE_PATH", "MyPkg/Include;MyPkg/Include/StandaloneMm", "Platform Defined") +``` + +This list must be the same length as the `MU_SCHEMA_FILE_NAME` and it will be processed in the same order; the first +schema file will get headers generated to the first include directory, etc. The platform must define `MU_SCHEMA_DIR` and `MU_SCHEMA_FILE_NAME` in PlatformBuild.py. These are the directory containing the XML configuration file and the file name of the XML configuration file, respectively. These are split apart to allow the CI build to discover a test schema to validate this process. +`MU_SCHEMA_FILE_NAME` may have multiple schema files that are semicolon delimited if the build has multiple environments +being built at the same time, e.g. StandaloneMM and DXE. If so, `CONF_AUTOGEN_INCLUDE_PATH` must have the same number of +entries, see above. An example is: + +```python +self.env.SetValue("MU_SCHEMA_FILE_NAME", "NonSecureConfig.xml;StMMConfig.xml", "Platform Defined") +``` + ### Autogenerated Header Files There are four autogenerated headers and one standard structure definition header: diff --git a/SetupDataPkg/Docs/Profiles/Overview.md b/SetupDataPkg/Docs/Profiles/Overview.md index 7ed44abf..122844ab 100644 --- a/SetupDataPkg/Docs/Profiles/Overview.md +++ b/SetupDataPkg/Docs/Profiles/Overview.md @@ -59,6 +59,12 @@ self.env.SetValue('CONF_PROFILE_PATHS', ) ``` +If `MU_SCHEMA_FILE_NAME` has multiple entries (see +[Platform Integration Steps](../PlatformIntegration/PlatformIntegrationSteps.md)), then there may be a semicolon +delimited list of `CONF_PROFILE_PATHS`. `UpdateConfigHdr.py` will match these in the same order as the schema files, +i.e. `CONF_PROFILE_PATHS` first entry will be applied to the first entry of `MU_SCHEMA_FILE_NAME`. If there is no +corresponding entry, it will be assumed there is no profile override to that schema file. + Platform owners can develop a configuration profile for their use case. Following examples and the format provided in the [ConfigurationFiles doc](../ConfigurationFiles/ConfigurationFiles.md), these owners can create an XML change file describing the set of configuration variables and their values that are in the profile that differ from the generic diff --git a/SetupDataPkg/Plugins/UpdateConfigHdr/UpdateConfigHdr.py b/SetupDataPkg/Plugins/UpdateConfigHdr/UpdateConfigHdr.py index 0d1c2cf8..e4ae607a 100644 --- a/SetupDataPkg/Plugins/UpdateConfigHdr/UpdateConfigHdr.py +++ b/SetupDataPkg/Plugins/UpdateConfigHdr/UpdateConfigHdr.py @@ -23,13 +23,17 @@ def do_pre_build(self, thebuilder): "SetupDataPkg", "Test", "Include" ) - final_dir = thebuilder.env.GetValue("CONF_AUTOGEN_INCLUDE_PATH", default_generated_path) + # we can have a semicolon delimited list of include paths to generate to + dirs = thebuilder.env.GetValue("CONF_AUTOGEN_INCLUDE_PATH", default_generated_path).split(";") + final_dirs = [] # Add Generated dir - final_dir = os.path.join(final_dir, "Generated") + for directory in dirs: + gen_dir = os.path.join(directory, "Generated") + final_dirs.append(gen_dir) - if not os.path.isdir(final_dir): - os.makedirs(final_dir) + if not os.path.isdir(gen_dir): + os.makedirs(gen_dir) # Add generate routine here cmd = thebuilder.edk2path.GetAbsolutePathOnThisSystemFromEdk2RelativePath( @@ -44,41 +48,54 @@ def do_pre_build(self, thebuilder): logging.error("MU_SCHEMA_DIR not set") return -1 - schema_file_name = thebuilder.env.GetValue("MU_SCHEMA_FILE_NAME", "testschema.xml") + # This may be a semicolon delimited string + schema_file_names = thebuilder.env.GetValue("MU_SCHEMA_FILE_NAME", "testschema.xml").split(";") + schema_files = [] - schema_file = thebuilder.edk2path.GetAbsolutePathOnThisSystemFromEdk2RelativePath(schema_dir, schema_file_name) + for name in schema_file_names: + file = thebuilder.edk2path.GetAbsolutePathOnThisSystemFromEdk2RelativePath(schema_dir, name) + schema_files.append(file) - if not os.path.isfile(schema_file): - logging.error(f"XML schema file \"{schema_file}\" specified is not found!!!") - return -1 + if not os.path.isfile(file): + logging.error(f"XML schema file \"{file}\" specified is not found!!!") + return -1 - # this is a space separated list of paths to CSV files describing the profiles for + # this is a semicolon delimited list of space separated lists of paths to CSV files describing the profiles for # this platform. It is allowed to be empty if there are no profiles. - profile_paths = thebuilder.env.GetValue("CONF_PROFILE_PATHS", "") + # e.g.: "CONF_PATH_1 CONF_PATH_2 CONF_PATH3;CONF_PATH4 CONF_PATH5 CONF_PATH6;CONF_PATH7 CONF_PATH8 CONF_PATH9" + profile_path_list = thebuilder.env.GetValue("CONF_PROFILE_PATHS", "").split(";") + + # this is a semicolon delimited list of comma separated 2 character profile names to pair with CSV files + # identifying the profiles. This field is optional. + profile_names = thebuilder.env.GetValue("CONF_PROFILE_NAMES", "").split(";") + profile_ids = thebuilder.env.GetValue("CONF_PROFILE_IDS", "").split(";") - # this is a comma separated 2 character profile names to pair with CSV files identifying - # the profiles. This field is optional. - profile_names = thebuilder.env.GetValue("CONF_PROFILE_NAMES", "") - profile_ids = thebuilder.env.GetValue("CONF_PROFILE_IDS", "") + if len(schema_files) != len(final_dirs): + logging.error("Differing number of items in CONF_AUTOGEN_INCLUDE_PATH and MU_SCHEMA_FILE_NAME!\ + They must be the same") + return -1 - params = ["generateheader_efi"] + for i in range(len(schema_files)): + params = ["generateheader_efi"] - params.append(schema_file) + params.append(schema_files[i]) - params.append("ConfigClientGenerated.h") - params.append("ConfigServiceGenerated.h") - params.append("ConfigDataGenerated.h") + params.append("ConfigClientGenerated.h") + params.append("ConfigServiceGenerated.h") + params.append("ConfigDataGenerated.h") - if profile_paths != "": - params.append("ConfigProfilesGenerated.h") - params.append(profile_paths) + if len(profile_path_list) > i and profile_path_list[i] != "": + params.append("ConfigProfilesGenerated.h") + params.append(profile_path_list[i]) - if profile_names != "": - params.append("-pn") - params.append(profile_names) - if profile_ids != "": - params.append("-pid") - params.append(profile_ids) + if len(profile_names) > i and profile_names[i] != "": + params.append("-pn") + params.append(profile_names[i]) + if len(profile_ids) > i and profile_ids[i] != "": + params.append("-pid") + params.append(profile_ids[i]) - ret = RunPythonScript(cmd, " ".join(params), workingdir=final_dir) - return ret + ret = RunPythonScript(cmd, " ".join(params), workingdir=final_dirs[i]) + if ret != 0: + return ret + return 0