From 2e9dd0ade2e310203a299e02e80f99393118635f Mon Sep 17 00:00:00 2001 From: Maxim Polyakov Date: Sat, 3 Dec 2022 22:41:42 +0300 Subject: [PATCH] util/intelp2m: Update cli options - Redesign the options format. - Add automatic completion of arguments for bash. [complete -C `pwd`/intelp2m ./intelp2m] to enable TEST: make test = PASS Change-Id: I08ff379b99b018b1099aa5d70fea47026bc84045 Signed-off-by: Maxim Polyakov Reviewed-on: https://review.coreboot.org/c/coreboot/+/70310 Reviewed-by: David Hendricks Tested-by: build bot (Jenkins) --- util/intelp2m/cli/completion.go | 22 +++ util/intelp2m/cli/options.go | 232 +++++++++++++++++++++++++++++ util/intelp2m/config/p2m/config.go | 4 +- util/intelp2m/main.go | 91 ++--------- util/intelp2m/version.txt | 2 +- 5 files changed, 270 insertions(+), 81 deletions(-) create mode 100644 util/intelp2m/cli/completion.go create mode 100644 util/intelp2m/cli/options.go diff --git a/util/intelp2m/cli/completion.go b/util/intelp2m/cli/completion.go new file mode 100644 index 0000000000..b322a87d10 --- /dev/null +++ b/util/intelp2m/cli/completion.go @@ -0,0 +1,22 @@ +package cli + +import ( + "flag" + "fmt" + "os" + "strings" +) + +func UseComplete() bool { + if _, ok := os.LookupEnv("COMP_LINE"); ok { + argument := os.Args[2] + argument = strings.TrimLeft(argument, "-") + flag.VisitAll(func(f *flag.Flag) { + if argument == "" || strings.HasPrefix(f.Name, argument) { + fmt.Println("-" + f.Name) + } + }) + return true + } + return false +} diff --git a/util/intelp2m/cli/options.go b/util/intelp2m/cli/options.go new file mode 100644 index 0000000000..c6adbcffd8 --- /dev/null +++ b/util/intelp2m/cli/options.go @@ -0,0 +1,232 @@ +package cli + +import ( + "flag" + "fmt" + "os" + "path/filepath" + + "review.coreboot.org/coreboot.git/util/intelp2m/config/p2m" +) + +var name = filepath.Base(os.Args[0]) + +const usagePlatform = `usage: -platform + type: adl | apl | cnl | ebg | jsl | lbg | mtl | snr | tgl | ? + adl - Alder Lake PCH + apl - Apollo Lake SoC + cnl - CannonLake-LP or Whiskeylake/Coffeelake/Cometlake-U SoC + ebg - Emmitsburg PCH with Xeon SP + jsl - Jasper Lake SoC + lbg - Lewisburg PCH with Xeon SP + mtl - MeteorLake SoC + snr - Sunrise PCH or Skylake/Kaby Lake SoC + tgl - TigerLake-H SoC + ? - show details +` +const usageFields = `usage: -fields + type: cb | fsp | raw | ? + cb - coreboot style + fsp - Intel FSP style + raw - raw register value (don't convert, print as is) + ? - show details +` +const usageExclude = `usage: -e | -exclude + Exclude fields that should be ignored to generate "short" macro. + Details: + The utility should ignore "PAD_TRIG(OFF)" field in the "_PAD_CFG_STRUCT(GPP_I12, + PAD_FUNC(GPIO) | PAD_RESET(PLTRST) | PAD_TRIG(OFF) | PAD_BUF(RX_DISABLE) | 1, 0)" + "long" macro to generate the "PAD_CFG_GPO(GPP_I12, 1, PLTRST)" macro. + + The utility with this option generates the "long" macro with only those fields that are + required to create the "short" one (in thia case without the "PAD_TRIG(OFF)" field): + "_PAD_CFG_STRUCT(GPP_I12, PAD_FUNC(GPIO) | PAD_RESET(PLTRST) | PAD_BUF(RX_DISABLE) | 1, 0)" +` + +const usageUnchecked = `usage: -u | -unchecked + Disable automatic bitfield checking before generating. + Details: + The utility automatically checks the bit fields of the DW registers before generating + the macro. If a bit is set in the register and it is not used in the "short" macro, the + utility will generate the "long" one instead of the first one. + + This option is used to disable automatic verification. In this case, all macros are + generated in the "short" format: + PAD_NC(GPP_F18, NONE), + PAD_CFG_NF(GPP_F19, NONE, PLTRST, NF1), + ... +` + +const usageInfo = `usage: -i | -ii | -iii | -iiii + Generate additional information about macros. + Level 1 information (-i): + _PAD_CFG_STRUCT(GPP_A4, PAD_FUNC(NF1) | PAD_RESET(PLTRST) | (1 << 1), 0), /* LAD3 */ + + Level 2 information (-ii): + /* GPP_A4 - LAD3 */ + /* DW0: 0x80000402, DW1: 0x00000000 */ + _PAD_CFG_STRUCT(GPP_A4, PAD_FUNC(NF1) | PAD_RESET(PLTRST) | (1 << 1), 0), + + Level 3 information (-iii): + /* GPP_A3 - LAD2 */ + /* DW0: 0x80000402, DW1: 0x00000000 */ + /* DW0: (1 << 1) - IGNORED */ + _PAD_CFG_STRUCT(GPP_A3, PAD_FUNC(NF1) | PAD_RESET(PLTRST) | (1 << 1), 0), + + Level 4 information (-iiii): + /* GPP_A4 - LAD3 */ + /* DW0: 0x80000402, DW1: 0x00000000 */ + /* DW0: (1 << 1) - IGNORED */ + /* PAD_CFG_NF(GPP_A4, NONE, PLTRST, NF1), */ + _PAD_CFG_STRUCT(GPP_A4, PAD_FUNC(NF1) | PAD_RESET(PLTRST) | (1 << 1), 0), +` + +const usage = ` +basic functions: + -h | -help Print help + -v | -version Print version + -file Set path to the inteltool file. by default + -out Set path to the generated file. by default + -p | -platform Set the PCH platform type. by default + (enter ? to show datails) + +generation of long composite macros with bit field definitions: + -f | -fields Set the bitfield type for the generated long macro + (enter ? to show datails) + +control flags: + -e | -exclude Exclude fields that should be ignored to generate short macro + -u | -unchecked Disable automatic bitfield checking before generating + (enter ? to show datails) + +generate additional information: + -i Add function to the comments + -ii Add DW0/DW1 register value to the comments + -iii Add ignored bitfields to the comments + -iiii Add target PAD_CFG() macro to the comments + (enter ? to show datails) +` + +func Usage() { + fmt.Printf(`usage: %s %s`, name, usage) +} + +func cbOptionsPlatform(value string) error { + if value == "?" { + fmt.Printf("%s", usagePlatform) + os.Exit(0) + } + + if err := p2m.SetPlatformType(value); err != nil { + fmt.Printf("error: %v\n%s", err, usagePlatform) + os.Exit(0) + } + + return nil +} + +func cbOptionsFields(value string) error { + if value == "?" { + fmt.Printf("%s", usageFields) + os.Exit(0) + } + + if err := p2m.SetFieldType(value); err != nil { + fmt.Printf("error: %v\n%s", err, usageFields) + os.Exit(0) + } + + return nil +} + +func cbOptionsExclude(_ string) error { + if numArgs := flag.NArg(); numArgs == 1 { + if flag.Arg(0) == "?" { + fmt.Printf("%s", usageExclude) + } + Usage() + os.Exit(0) + } + p2m.Config.IgnoredFields = true + return nil +} + +func cbOptionsUnchecked(_ string) error { + if numArgs := flag.NArg(); numArgs == 1 { + if flag.Arg(0) == "?" { + fmt.Printf("%s", usageUnchecked) + } + Usage() + os.Exit(0) + } + p2m.Config.AutoCheck = false + return nil +} + +func cbOptionsInfo(_ string) error { + if numArgs := flag.NArg(); numArgs == 1 { + if flag.Arg(0) == "?" { + fmt.Printf("%s", usageInfo) + os.Exit(0) + } + Usage() + os.Exit(0) + } + + table := map[string]int{ + "-i": 1, + "-ii": 2, + "-iii": 3, + "-iiii": 4, + } + for _, arg := range os.Args { + if level, exist := table[arg]; exist { + p2m.Config.GenLevel = level + return nil + } + } + Usage() + return nil +} + +func ParseOptions() { + flag.Usage = Usage + flag.StringVar(&p2m.Config.InputPath, "file", "inteltool.log", "") + flag.StringVar(&p2m.Config.OutputPath, "out", "generate/gpio.h", "") + help := flag.Bool("help", false, "") + + vers, v := flag.Bool("version", false, ""), flag.Bool("v", false, "") + + flag.Func("platform", usagePlatform, cbOptionsPlatform) + flag.Func("p", usagePlatform, cbOptionsPlatform) + + flag.Func("fields", usageFields, cbOptionsFields) + flag.Func("f", usageFields, cbOptionsFields) + + flag.BoolFunc("exclude", usageExclude, cbOptionsExclude) + flag.BoolFunc("e", usageExclude, cbOptionsExclude) + + flag.BoolFunc("unchecked", usageUnchecked, cbOptionsUnchecked) + flag.BoolFunc("u", usageUnchecked, cbOptionsUnchecked) + + flag.BoolFunc("i", usageInfo, cbOptionsInfo) + flag.BoolFunc("ii", usageInfo, cbOptionsInfo) + flag.BoolFunc("iii", usageInfo, cbOptionsInfo) + flag.BoolFunc("iiii", usageInfo, cbOptionsInfo) + + if UseComplete() { + os.Exit(0) + } + + flag.Parse() + + if *help { + Usage() + os.Exit(0) + } + + if *vers || *v { + fmt.Println(p2m.Config.Version) + os.Exit(0) + } +} diff --git a/util/intelp2m/config/p2m/config.go b/util/intelp2m/config/p2m/config.go index ce03ee0c36..07efb5b7bb 100644 --- a/util/intelp2m/config/p2m/config.go +++ b/util/intelp2m/config/p2m/config.go @@ -50,6 +50,8 @@ type Settings struct { Version string Platform PlatformType Field FieldType + InputPath string + OutputPath string InputFile *os.File OutputFile *os.File IgnoredFields bool @@ -60,7 +62,7 @@ type Settings struct { var Config = Settings{ Version: "unknown", Platform: Sunrise, - Field: CbFlds, + Field: NoFlds, IgnoredFields: false, AutoCheck: true, GenLevel: 0, diff --git a/util/intelp2m/main.go b/util/intelp2m/main.go index f0e2203c3f..47a1516c98 100644 --- a/util/intelp2m/main.go +++ b/util/intelp2m/main.go @@ -1,11 +1,11 @@ package main import ( - "flag" "fmt" "os" "path/filepath" + "review.coreboot.org/coreboot.git/util/intelp2m/cli" "review.coreboot.org/coreboot.git/util/intelp2m/config/p2m" "review.coreboot.org/coreboot.git/util/intelp2m/parser" ) @@ -24,101 +24,34 @@ func (Printer) Line(lvl int, str string) { } } -var ( - // Version is injected into main during project build - Version string = "Unknown" -) - -// printVersion - print the utility version in the console -func printVersion() { - fmt.Printf("[ intelp2m ] Version: %s\n", Version) -} +// Version is injected into main during project build +var Version string = "Unknown" // main func main() { - // Command line arguments - inputFilePath := flag.String("file", "inteltool.log", - "the path to the inteltool log file\n") - - outputFilePath := flag.String("o", - "generate/gpio.h", - "the path to the generated file with GPIO configuration\n") - - ignored := flag.Bool("ign", false, - "exclude fields that should be ignored from advanced macros\n") - - unchecking := flag.Bool("n", false, - "Generate macros without checking.\n"+ - "\tIn this case, some fields of the configuration registers\n"+ - "\tDW0 will be ignored.\n") - - levels := []*bool{ - flag.Bool("i", false, "Show pads function in the comments"), - flag.Bool("ii", false, "Show DW0/DW1 value in the comments"), - flag.Bool("iii", false, "Show ignored bit fields in the comments"), - flag.Bool("iiii", false, "Show target PAD_CFG() macro in the comments"), - } - - platform := flag.String("p", "snr", "set platform:\n"+ - "\tsnr - Sunrise PCH or Skylake/Kaby Lake SoC\n"+ - "\tlbg - Lewisburg PCH with Xeon SP\n"+ - "\tapl - Apollo Lake SoC\n"+ - "\tcnl - CannonLake-LP or Whiskeylake/Coffeelake/Cometlake-U SoC\n"+ - "\ttgl - TigerLake-H SoC\n"+ - "\tadl - AlderLake PCH\n"+ - "\tjsl - Jasper Lake SoC\n"+ - "\tmtl - MeteorLake SoC\n"+ - "\tebg - Emmitsburg PCH with Xeon SP\n") - - field := flag.String("fld", "none", "set fields macros style:\n"+ - "\tcb - use coreboot style for bit fields macros\n"+ - "\tfsp - use fsp style\n"+ - "\traw - do not convert, print as is\n") - - flag.Parse() - printVersion() - - // settings p2m.Config.Version = Version - p2m.Config.IgnoredFields = *ignored - p2m.Config.AutoCheck = !(*unchecking) - for level, set := range levels { - if *set { - p2m.Config.GenLevel = level + 1 - fmt.Printf("Info level: Use level %d!\n", level+1) - break - } - } - if err := p2m.SetPlatformType(*platform); err != nil { - fmt.Printf("Error: %v\n", err) - os.Exit(1) - } + cli.ParseOptions() - if err := p2m.SetFieldType(*field); err != nil { - fmt.Printf("Error: %v\n", err) - os.Exit(1) - } - - if file, err := os.Open(*inputFilePath); err != nil { - fmt.Printf("input file error: %v", err) + if file, err := os.Open(p2m.Config.InputPath); err != nil { + fmt.Printf("input file error: %v\n", err) os.Exit(1) } else { p2m.Config.InputFile = file + defer file.Close() } - defer p2m.Config.InputFile.Close() - if err := os.MkdirAll(filepath.Dir(*outputFilePath), os.ModePerm); err != nil { - fmt.Printf("failed to create output directory: %v", err) + if err := os.MkdirAll(filepath.Dir(p2m.Config.OutputPath), os.ModePerm); err != nil { + fmt.Printf("failed to create output directory: %v\n", err) os.Exit(1) } - if file, err := os.Create(*outputFilePath); err != nil { - fmt.Printf("failed to create output file: %v", err) + if file, err := os.Create(p2m.Config.OutputPath); err != nil { + fmt.Printf("failed to create output file: %v\n", err) os.Exit(1) } else { p2m.Config.OutputFile = file + defer file.Close() } - defer p2m.Config.OutputFile.Close() prs := parser.ParserData{} prs.Parse() diff --git a/util/intelp2m/version.txt b/util/intelp2m/version.txt index 5625e59da8..7e32cd5698 100644 --- a/util/intelp2m/version.txt +++ b/util/intelp2m/version.txt @@ -1 +1 @@ -1.2 +1.3