Skip to content

Commit

Permalink
Update autogen script for profile names on UEFI builds (#207)
Browse files Browse the repository at this point in the history
# Preface

Please ensure you have read the [contribution
docs](https://github.com/microsoft/mu/blob/master/CONTRIBUTING.md) prior
to submitting the pull request. In particular,
[pull request
guidelines](https://github.com/microsoft/mu/blob/master/CONTRIBUTING.md#pull-request-best-practices).

## Description

This change updated the autogen script to populate the profile names
into profile header. The script will accept `-pn` as an input argument
for the comma separated profile names.

This autogen script is also hooked up to `CONF_PROFILE_NAMES` build
variable to allow UEFI platform build to specify names through
variables. If platform elects not to specify such argument, the indices
will be used for such names during autogen process.

A header file is also created for `PlatformConfigDataLib` to indicate
what global variables will be produced by the autogen scripts and should
serve as a contract between the autogen script and any data library
should the consumer choose to implement so.

Fixes #205 

For each item, place an "x" in between `[` and `]` if true. Example:
`[x]`.
_(you can also check items in the GitHub UI)_

- [x] Impacts functionality?
- **Functionality** - Does the change ultimately impact how firmware
functions?
- Examples: Add a new library, publish a new PPI, update an algorithm,
...
- [ ] Impacts security?
- **Security** - Does the change have a direct security impact on an
application,
    flow, or firmware?
  - Examples: Crypto algorithm change, buffer overflow fix, parameter
    validation improvement, ...
- [ ] Breaking change?
- **Breaking change** - Will anyone consuming this change experience a
break
    in build or boot behavior?
- Examples: Add a new library class, move a module to a different repo,
call
    a function in a new library class in a pre-existing module, ...
- [ ] Includes tests?
  - **Tests** - Does the change include any explicit test code?
  - Examples: Unit tests, integration tests, robot tests, ...
- [ ] Includes documentation?
- **Documentation** - Does the change contain explicit documentation
additions
    outside direct code modifications (and comments)?
- Examples: Update readme file, add feature readme file, link to
documentation
    on an a separate Web page, ...

## How This Was Tested

This was tested on QEMU Q35 and SBSA platforms.

## Integration Instructions

Specify the `CONF_PROFILE_NAMES` build variable as comma separated
strings during prebuild phase if need to customize.
  • Loading branch information
kuqin12 authored Jun 22, 2023
1 parent a4a522d commit fb5a9e8
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 4 deletions.
3 changes: 2 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
"ntdll",
"NTSTATUS",
"PVARIABLE",
"ANYSIZE"
"ANYSIZE",
"profilenames"
]
}
2 changes: 2 additions & 0 deletions SetupDataPkg/Include/ConfigStdStructDefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#ifndef CONFIG_STD_STRUCT_DEFS_LIB_H_
#define CONFIG_STD_STRUCT_DEFS_LIB_H_

#define PROFILE_FLAVOR_NAME_LENGTH 3

/*
* Standard structure definitons that KnobService.py autogenerated
* headers and core code use.
Expand Down
28 changes: 28 additions & 0 deletions SetupDataPkg/Include/Library/PlatformConfigDataLib.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/** @file
Global variables from configuration data created by autogen header.
Note: The data fields in this file is originated from the autogen script.
One should not change the content in this file without pairing the
autogen scripts.
Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#ifndef PLATFORM_CONFIG_DATA_LIB_H_
#define PLATFORM_CONFIG_DATA_LIB_H_

#include <Uefi.h>
#include <ConfigStdStructDefs.h>

extern KNOB_DATA gKnobData[];
extern UINTN gNumKnobs;
extern PROFILE gProfileData[];
// number of profile overrides (i.e. into gProfileData)
// this does not count the generic profile, which is not
// in gProfileData, but rather in gKnobData's defaults
extern UINTN gNumProfiles;
extern CHAR8 *gProfileFlavorName;

#endif // PLATFORM_CONFIG_DATA_LIB_H_
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* @file PlatformConfigDataLibNull.c
Null instance of PlatformConfigDataLib. Platform is expected to implement this library and
supply autogenerated data structures.
Copyright (c) Microsoft Corporation.
**/

#include <Uefi.h>
#include <ConfigStdStructDefs.h>

KNOB_DATA gKnobData = { 0 };

UINTN gNumKnobs = 0;

PROFILE gProfileData = { 0 };

CHAR8 *gProfileFlavorName = { 0 };

UINTN gNumProfiles = 0;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
## @file PlatformConfigDataLibNull.inf
#
# Null instance of PlatformConfigDataLib. The platform is expected to implement this library and
# supply autogenerated data structures.
#
# Copyright (c) Microsoft Corporation.
#
##


[Defines]
INF_VERSION = 0x00010017
BASE_NAME = PlatformConfigDataNullLib
FILE_GUID = 88C6BBE4-419C-42A0-BAE7-CC2CA37E1801
VERSION_STRING = 1.0
MODULE_TYPE = BASE
LIBRARY_CLASS = NULL

#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = ANY
#

[Sources]
PlatformConfigDataLibNull.c

[Packages]
MdePkg/MdePkg.dec
SetupDataPkg/SetupDataPkg.dec

[Depex]
# This library is intended to have no dependencies and only carry data
TRUE
10 changes: 9 additions & 1 deletion SetupDataPkg/Plugins/UpdateConfigHdr/UpdateConfigHdr.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class UpdateConfigHdr(IUefiBuildPlugin):
# Attempt to run GenCfgData to generate C header files
#
# Consumes build environment variables: "CONF_AUTOGEN_INCLUDE_PATH", "MU_SCHEMA_DIR",
# "MU_SCHEMA_FILE_NAME", and "CONF_PROFILE_PATHS"
# "MU_SCHEMA_FILE_NAME", "CONF_PROFILE_PATHS" and "CONF_PROFILE_NAMES"
def do_pre_build(self, thebuilder):
default_generated_path = thebuilder.mws.join(thebuilder.ws, "SetupDataPkg", "Test", "Include")

Expand Down Expand Up @@ -52,6 +52,10 @@ def do_pre_build(self, thebuilder):
# this platform. It is allowed to be empty if there are no profiles.
profile_paths = thebuilder.env.GetValue("CONF_PROFILE_PATHS", "")

# 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", "")

params = ["generateheader_efi"]

params.append(schema_file)
Expand All @@ -64,5 +68,9 @@ def do_pre_build(self, thebuilder):
params.append("ConfigProfilesGenerated.h")
params.append(profile_paths)

if profile_names != "":
params.append("-pn")
params.append(profile_names)

ret = RunPythonScript(cmd, " ".join(params), workingdir=final_dir)
return ret
1 change: 1 addition & 0 deletions SetupDataPkg/SetupDataPkg.dec
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
SvdXmlSettingSchemaSupportLib|Include/Library/SvdXmlSettingSchemaSupportLib.h
ConfigKnobShimLib|Include/Library/ConfigKnobShimLib.h
ActiveProfileIndexSelectorLib|Include/Library/ActiveProfileIndexSelectorLib.h
PlatformConfigDataLib|Include/Library/PlatformConfigDataLib.h

[Guids]
gSetupDataPkgTokenSpaceGuid = { 0x0651d23a, 0xe244, 0x4a7f, { 0x8d, 0x2e, 0x37, 0xac, 0x2b, 0xf9, 0x32, 0xff } }
Expand Down
1 change: 1 addition & 0 deletions SetupDataPkg/SetupDataPkg.dsc
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
SetupDataPkg/Library/ConfigKnobShimLib/ConfigKnobShimDxeLib/ConfigKnobShimDxeLib.inf
SetupDataPkg/Library/SvdXmlSettingSchemaSupportLib/SvdXmlSettingSchemaSupportLib.inf
SetupDataPkg/Library/ActiveProfileIndexSelectorLibNull/ActiveProfileIndexSelectorLibNull.inf
SetupDataPkg/Library/PlatformConfigDataLibNull/PlatformConfigDataLibNull.inf

[Components.X64, Components.AARCH64]
SetupDataPkg/ConfApp/ConfApp.inf
Expand Down
53 changes: 51 additions & 2 deletions SetupDataPkg/Tools/KnobService.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import os
import sys
import uuid
import argparse
import re
import VariableList

Expand Down Expand Up @@ -978,7 +979,7 @@ def generate_getter_implementation(schema, header_path, efi_type):
out.write(get_include_once_style(header_path, uefi=efi_type, header=False))


def generate_profiles(schema, profile_header_path, profile_paths, efi_type):
def generate_profiles(schema, profile_header_path, profile_paths, efi_type, profile_names=None):
with open(profile_header_path, 'w', newline='') as out:
out.write(get_spdx_header(profile_header_path, efi_type))
out.write(get_include_once_style(profile_header_path, uefi=efi_type, header=True))
Expand Down Expand Up @@ -1113,6 +1114,20 @@ def generate_profiles(schema, profile_header_path, profile_paths, efi_type):
out.write(get_spacing_string(efi_type) + "}" + get_line_ending(efi_type))
out.write("};" + get_line_ending(efi_type))
if efi_type:
if profile_names is not None:
names_list = profile_names.split(",")
else:
# If not specified, the indices will be the default profile names
names_list = [format(i, '02x') for i in range(len(profile_paths))]

out.write(get_line_ending(efi_type))
out.write(get_type_string("char*", efi_type) + " g{}[PROFILE_COUNT]".format(
naming_convention_filter("_profile_flavor_name", False, efi_type)) + " = {"
)
out.write(get_line_ending(efi_type))
for profile_name in names_list:
out.write(get_spacing_string(efi_type) + '"' + profile_name + '",' + get_line_ending(efi_type))
out.write("};" + get_line_ending(efi_type))
out.write(get_line_ending(efi_type))
out.write(get_type_string("size_t", efi_type) + " g{} = PROFILE_COUNT;".format(
naming_convention_filter("_num_profiles", False, efi_type))
Expand Down Expand Up @@ -1150,9 +1165,27 @@ def usage():
print(" by config providers.")
print("profile.csv... : n-number of profile csvs that describe the platform's")
print(" overridden config knobs")
print("-pn names : n-number of 2-character profile names that uniquely identify the")
print(" profiles specified in profile.csv")


def arg_parse():
parser = argparse.ArgumentParser()

parser.add_argument(
'-pn', '--profilenames', dest='profile_names', type=str, default=None,
help='''Specify the comma separated profile names by passing -pn <Name1,Name2> '''
'''or --profilenames <Name1,Name2,Name3>.''')

return parser.parse_known_args()


def main():
# We should not overload the positional argument anymore given we are accepting nondeterministic number of space
# separated profile paths... So please add the new ones here...
known_args, left_over = arg_parse()
sys.argv = sys.argv[:1] + left_over

arg_num = 1
if len(sys.argv) < 2:
usage()
Expand Down Expand Up @@ -1198,7 +1231,23 @@ def main():
arg_num += 1
profile_paths = sys.argv[arg_num:]

generate_profiles(schema, profile_header_path, profile_paths, efi_type)
if known_args.profile_names is not None:
# Do some minimal sanity checks
names = known_args.profile_names.split(",")
if len(names) != len(profile_paths):
sys.stderr.write('Invalid count of profile names %d.\n' % len(names))
return -1

lengths = [len(name) for name in names]
max_length = max(lengths)
min_length = min(lengths)

if max_length != 2 or min_length != 2:
sys.stderr.write('Invalid profile names, should be 2-character for all entries.\n')
return -1

generate_profiles(schema, profile_header_path, profile_paths, efi_type,
profile_names=known_args.profile_names)
return 0


Expand Down

0 comments on commit fb5a9e8

Please sign in to comment.