Matt DeVillier has submitted this change. ( https://review.coreboot.org/c/coreboot/+/67701?usp=email )
Change subject: util/intelp2m/parser: Add unit test ......................................................................
util/intelp2m/parser: Add unit test
Also add an interface for printing macros to override this in the test and not create a new gpio file for comparison.
Change-Id: I16c9b4451cd4418b49043a925cb879a982a56461 Signed-off-by: Maxim Polyakov max.senia.poliak@gmail.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/67701 Reviewed-by: Maximilian Brune maximilian.brune@9elements.com Tested-by: build bot (Jenkins) no-reply@coreboot.org --- M util/intelp2m/main.go M util/intelp2m/parser/parser.go A util/intelp2m/parser/parser_test.go A util/intelp2m/parser/test/inteltool_test.log 4 files changed, 292 insertions(+), 126 deletions(-)
Approvals: Maximilian Brune: Looks good to me, approved build bot (Jenkins): Verified
diff --git a/util/intelp2m/main.go b/util/intelp2m/main.go index 1f3333b..5e17721 100644 --- a/util/intelp2m/main.go +++ b/util/intelp2m/main.go @@ -9,6 +9,20 @@ "review.coreboot.org/coreboot.git/util/intelp2m/parser" )
+type Printer struct{} + +func (Printer) Linef(lvl int, format string, args ...interface{}) { + if config.InfoLevelGet() >= lvl { + fmt.Fprintf(config.OutputGenFile, format, args...) + } +} + +func (Printer) Line(lvl int, str string) { + if config.InfoLevelGet() >= lvl { + fmt.Fprint(config.OutputGenFile, str) + } +} + var ( // Version is injected into main during project build Version string = "Unknown" @@ -19,28 +33,6 @@ fmt.Printf("[ intelp2m ] Version: %s\n", Version) }
-// generateOutputFile - generates include file -// parser : parser data structure -func generateOutputFile(parser *parser.ParserData) (err error) { - header := fmt.Sprintf(`/* SPDX-License-Identifier: GPL-2.0-only */ - -#ifndef CFG_GPIO_H -#define CFG_GPIO_H - -#include <gpio.h> - -/* Pad configuration was generated automatically using intelp2m %s */ -static const struct pad_config gpio_table[] = {`, Version) - config.OutputGenFile.WriteString(header + "\n") - // Add the pads map - parser.PadMapFprint() - config.OutputGenFile.WriteString(`}; - -#endif /* CFG_GPIO_H */ -`) - return nil -} - // main func main() { // Command line arguments @@ -148,13 +140,31 @@ config.OutputGenFile = outputGenFile config.InputRegDumpFile = inputRegDumpFile
- parser := parser.ParserData{} - parser.Parse() + prs := parser.ParserData{} + prs.Parse()
- // gpio.h - err = generateOutputFile(&parser) - if err != nil { - fmt.Printf("Error! Can not create the file with GPIO configuration!\n") + generator := parser.Generator{ + PrinterIf: Printer{}, + Data: &prs, + } + header := fmt.Sprintf(`/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef CFG_GPIO_H +#define CFG_GPIO_H + +#include <gpio.h> + +/* Pad configuration was generated automatically using intelp2m %s */ +static const struct pad_config gpio_table[] = {`, Version) + config.OutputGenFile.WriteString(header + "\n") + // Add the pads map + + if err := generator.Run(); err != nil { + fmt.Printf("Error: %v", err) os.Exit(1) } + config.OutputGenFile.WriteString(`}; + +#endif /* CFG_GPIO_H */ +`) } diff --git a/util/intelp2m/parser/parser.go b/util/intelp2m/parser/parser.go index f6ed047..c30c695 100644 --- a/util/intelp2m/parser/parser.go +++ b/util/intelp2m/parser/parser.go @@ -2,21 +2,22 @@
import ( "bufio" + "errors" "fmt" - "strings" "strconv" + "strings"
- "review.coreboot.org/coreboot.git/util/intelp2m/platforms/common" - "review.coreboot.org/coreboot.git/util/intelp2m/platforms/snr" - "review.coreboot.org/coreboot.git/util/intelp2m/platforms/lbg" + "review.coreboot.org/coreboot.git/util/intelp2m/config" + "review.coreboot.org/coreboot.git/util/intelp2m/platforms/adl" "review.coreboot.org/coreboot.git/util/intelp2m/platforms/apl" "review.coreboot.org/coreboot.git/util/intelp2m/platforms/cnl" - "review.coreboot.org/coreboot.git/util/intelp2m/platforms/tgl" - "review.coreboot.org/coreboot.git/util/intelp2m/platforms/adl" - "review.coreboot.org/coreboot.git/util/intelp2m/platforms/jsl" - "review.coreboot.org/coreboot.git/util/intelp2m/platforms/mtl" + "review.coreboot.org/coreboot.git/util/intelp2m/platforms/common" "review.coreboot.org/coreboot.git/util/intelp2m/platforms/ebg" - "review.coreboot.org/coreboot.git/util/intelp2m/config" + "review.coreboot.org/coreboot.git/util/intelp2m/platforms/jsl" + "review.coreboot.org/coreboot.git/util/intelp2m/platforms/lbg" + "review.coreboot.org/coreboot.git/util/intelp2m/platforms/mtl" + "review.coreboot.org/coreboot.git/util/intelp2m/platforms/snr" + "review.coreboot.org/coreboot.git/util/intelp2m/platforms/tgl" )
// PlatformSpecific - platform-specific interface @@ -42,57 +43,16 @@ ownership uint8 }
-// generate - wrapper for Fprintf(). Writes text to the file specified -// in config.OutputGenFile -func (info *padInfo) generate(lvl int, line string, a ...interface{}) { - if config.InfoLevelGet() >= lvl { - fmt.Fprintf(config.OutputGenFile, line, a...) - } -} - -// titleFprint - print GPIO group title to file -// /* ------- GPIO Group GPP_L ------- */ -func (info *padInfo) titleFprint() { - info.generate(0, "\n\t/* %s */\n", info.function) -} - -// reservedFprint - print reserved GPIO to file as comment -// /* GPP_H17 - RESERVED */ -func (info *padInfo) reservedFprint() { - info.generate(2, "\n") - // small comment about reserved port - info.generate(0, "\t/* %s - %s */\n", info.id, info.function) -} - -// padInfoMacroFprint - print information about current pad to file using -// special macros: -// PAD_CFG_NF(GPP_F1, 20K_PU, PLTRST, NF1), /* SATAXPCIE4 */ -// gpio : gpio.c file descriptor -// macro : string of the generated macro -func (info *padInfo) padInfoMacroFprint(macro string) { - info.generate(2, - "\n\t/* %s - %s */\n\t/* DW0: 0x%0.8x, DW1: 0x%0.8x */\n", - info.id, - info.function, - info.dw0, - info.dw1) - info.generate(0, "\t%s", macro) - if config.InfoLevelGet() == 1 { - info.generate(1, "\t/* %s */", info.function) - } - info.generate(0, "\n") -} - // ParserData - global data // line : string from the configuration file // padmap : pad info map // RawFmt : flag for generating pads config file with DW0/1 reg raw values // Template : structure template type of ConfigFile type ParserData struct { - platform PlatformSpecific - line string - padmap []padInfo - ownership map[string]uint32 + platform PlatformSpecific + line string + padmap []padInfo + ownership map[string]uint32 }
// hostOwnershipGet - get the host software ownership value for the corresponding @@ -118,14 +78,14 @@ var dw0, dw1 uint32 var template = map[int]template{ config.TempInteltool: UseInteltoolLogTemplate, - config.TempGpioh : useGpioHTemplate, - config.TempSpec : useYourTemplate, + config.TempGpioh: useGpioHTemplate, + config.TempSpec: useYourTemplate, } if template[config.TemplateGet()](parser.line, &function, &id, &dw0, &dw1) == 0 { pad := padInfo{id: id, - function: function, - dw0: dw0, - dw1: dw1, + function: function, + dw0: dw0, + dw1: dw1, ownership: parser.hostOwnershipGet(id)} parser.padmap = append(parser.padmap, pad) return 0 @@ -143,56 +103,46 @@ // PlatformSpecificInterfaceSet - specific interface for the platform selected // in the configuration func (parser *ParserData) PlatformSpecificInterfaceSet() { - var platform = map[uint8]PlatformSpecific { - config.SunriseType : snr.PlatformSpecific{}, + var platform = map[uint8]PlatformSpecific{ + config.SunriseType: snr.PlatformSpecific{}, // See platforms/lbg/macro.go - config.LewisburgType : lbg.PlatformSpecific{ - InheritanceTemplate : snr.PlatformSpecific{}, + config.LewisburgType: lbg.PlatformSpecific{ + InheritanceTemplate: snr.PlatformSpecific{}, }, - config.ApolloType : apl.PlatformSpecific{}, - config.CannonType : cnl.PlatformSpecific{ - InheritanceTemplate : snr.PlatformSpecific{}, + config.ApolloType: apl.PlatformSpecific{}, + config.CannonType: cnl.PlatformSpecific{ + InheritanceTemplate: snr.PlatformSpecific{}, }, - config.TigerType : tgl.PlatformSpecific{}, - config.AlderType : adl.PlatformSpecific{}, - config.JasperType : jsl.PlatformSpecific{}, - config.MeteorType : mtl.PlatformSpecific{}, + config.TigerType: tgl.PlatformSpecific{}, + config.AlderType: adl.PlatformSpecific{}, + config.JasperType: jsl.PlatformSpecific{}, + config.MeteorType: mtl.PlatformSpecific{}, // See platforms/ebg/macro.go - config.EmmitsburgType : ebg.PlatformSpecific{ - InheritanceTemplate : cnl.PlatformSpecific{ - InheritanceTemplate : snr.PlatformSpecific{}, + config.EmmitsburgType: ebg.PlatformSpecific{ + InheritanceTemplate: cnl.PlatformSpecific{ + InheritanceTemplate: snr.PlatformSpecific{}, }, }, } parser.platform = platform[config.PlatformGet()] }
-// PadMapFprint - print pad info map to file -func (parser *ParserData) PadMapFprint() { - for _, pad := range parser.padmap { - switch pad.dw0 { - case 0: - pad.titleFprint() - case 0xffffffff: - pad.reservedFprint() - default: - str := parser.platform.GenMacro(pad.id, pad.dw0, pad.dw1, pad.ownership) - pad.padInfoMacroFprint(str) - } - } -} - // Register - read specific platform registers (32 bits) // line : string from file with pad config map // nameTemplate : register name femplate to filter parsed lines // return -// valid : true if the dump of the register in intertool.log is set in accordance -// with the template -// name : full register name -// offset : register offset relative to the base address -// value : register value +// +// valid : true if the dump of the register in intertool.log is set in accordance +// with the template +// name : full register name +// offset : register offset relative to the base address +// value : register value func (parser *ParserData) Register(nameTemplate string) ( - valid bool, name string, offset uint32, value uint32) { + valid bool, + name string, + offset uint32, + value uint32, +) { if strings.Contains(parser.line, nameTemplate) && config.TemplateGet() == config.TempInteltool { if registerInfoTemplate(parser.line, &name, &offset, &value) == 0 { @@ -204,7 +154,8 @@ }
// padOwnershipExtract - extract Host Software Pad Ownership from inteltool dump -// return true if success +// +// return true if success func (parser *ParserData) padOwnershipExtract() bool { var group string status, name, offset, value := parser.Register("HOSTSW_OWN_GPP_") @@ -212,13 +163,14 @@ _, group = parser.platform.GroupNameExtract(parser.line) parser.ownership[group] = value fmt.Printf("\n\t/* padOwnershipExtract: [offset 0x%x] %s = 0x%x */\n", - offset, name, parser.ownership[group]) + offset, name, parser.ownership[group]) } return status }
// padConfigurationExtract - reads GPIO configuration registers and returns true if the -// information from the inteltool log was successfully parsed. +// +// information from the inteltool log was successfully parsed. func (parser *ParserData) padConfigurationExtract() bool { // Only for Sunrise or CannonLake, and only for inteltool.log file template if config.TemplateGet() != config.TempInteltool || config.IsPlatformApollo() { @@ -242,7 +194,7 @@ scanner := bufio.NewScanner(config.InputRegDumpFile) for scanner.Scan() { parser.line = scanner.Text() - isIncluded, _ := common.KeywordsCheck(parser.line, "GPIO Community", "GPIO Group"); + isIncluded, _ := common.KeywordsCheck(parser.line, "GPIO Community", "GPIO Group") if isIncluded { parser.communityGroupExtract() } else if !parser.padConfigurationExtract() && parser.platform.KeywordCheck(parser.line) { @@ -253,3 +205,48 @@ } fmt.Println("...done!") } + +type PrinterIf interface { + Linef(lvl int, format string, args ...interface{}) + Line(lvl int, str string) +} + +type Generator struct { + Data *ParserData // information from the parser + PrinterIf // interface for printing +} + +// Run - generate a new gpio file based on the information from the parser +func (g Generator) Run() error { + if g.PrinterIf == nil && g.Data == nil { + return errors.New("Generator: Incorrect initialization") + } + for _, pad := range g.Data.padmap { + switch pad.dw0 { + case 0x00000000: + // titleFprint - print GPIO group title to file + // /* ------- GPIO Group GPP_L ------- */ + g.Linef(0, "\n\t/* %s */\n", pad.function) + case 0xffffffff: + // reservedFprint - print reserved GPIO to file as comment + // /* GPP_H17 - RESERVED */ + g.Line(2, "\n") + // small comment about reserved port + g.Linef(0, "\t/* %s - %s */\n", pad.id, pad.function) + default: + // padInfoMacroFprint - print information about current pad to file using + // special macros: + // PAD_CFG_NF(GPP_F1, 20K_PU, PLTRST, NF1), /* SATAXPCIE4 */ + platform := g.Data.platform + macro := platform.GenMacro(pad.id, pad.dw0, pad.dw1, pad.ownership) + g.Linef(2, "\n\t/* %s - %s */\n\t/* DW0: 0x%0.8x, DW1: 0x%0.8x */\n", + pad.id, pad.function, pad.dw0, pad.dw1) + g.Linef(0, "\t%s", macro) + if config.InfoLevelGet() == 1 { + g.Linef(1, "\t/* %s */", pad.function) + } + g.Line(0, "\n") + } + } + return nil +} diff --git a/util/intelp2m/parser/parser_test.go b/util/intelp2m/parser/parser_test.go new file mode 100644 index 0000000..4f0e452 --- /dev/null +++ b/util/intelp2m/parser/parser_test.go @@ -0,0 +1,104 @@ +package parser_test + +import ( + "fmt" + "os" + "testing" + + "review.coreboot.org/coreboot.git/util/intelp2m/config" + "review.coreboot.org/coreboot.git/util/intelp2m/parser" +) + +const testLogFilePath = "test/inteltool_test.log" + +type Printer struct { + lines []string +} + +func (p *Printer) Linef(lvl int, format string, args ...interface{}) { + if config.InfoLevelGet() >= lvl { + p.lines = append(p.lines, fmt.Sprintf(format, args...)) + } +} + +func (p *Printer) Line(lvl int, str string) { + if config.InfoLevelGet() >= lvl { + p.lines = append(p.lines, str) + } +} + +func TestParser(t *testing.T) { + t.Run("PARSER/PARSE-INTELTOOL-FILE", func(t *testing.T) { + reference := []string{ + "\n\t/* ------- GPIO Community 0 ------- */\n", + "\n\t/* ------- GPIO Group GPP_A ------- */\n", + "\tPAD_CFG_NF(GPP_A0, NONE, PLTRST, NF1),", "\t/* RCIN# */", "\n", + "\tPAD_CFG_NF(GPP_A1, UP_20K, PLTRST, NF1),", "\t/* LAD0 */", "\n", + "\tPAD_CFG_NF(GPP_A5, NONE, PLTRST, NF1),", "\t/* LFRAME# */", "\n", + "\tPAD_CFG_NF(GPP_A13, NONE, DEEP, NF1),", "\t/* SUSWARN#/SUSPWRDNACK */", "\n", + "\tPAD_CFG_GPI_TRIG_OWN(GPP_A23, NONE, PLTRST, OFF, ACPI),", "\t/* GPIO */", "\n", + "\n\t/* ------- GPIO Group GPP_B ------- */\n", + "\t/* GPP_C1 - RESERVED */\n", + "\tPAD_CFG_GPI_TRIG_OWN(GPP_B0, NONE, PLTRST, OFF, ACPI),", "\t/* GPIO */", "\n", + "\tPAD_CFG_NF(GPP_B23, DN_20K, PLTRST, NF2),", "\t/* PCHHOT# */", "\n", + "\n\t/* ------- GPIO Community 1 ------- */\n", + "\n\t/* ------- GPIO Group GPP_C ------- */\n", + "\tPAD_CFG_NF(GPP_C0, NONE, DEEP, NF1),", "\t/* SMBCLK */", "\n", + "\tPAD_CFG_GPI_TRIG_OWN(GPP_C5, NONE, PLTRST, OFF, ACPI),", "\t/* GPIO */", "\n", + "\t/* GPP_C6 - RESERVED */\n", + "\t/* GPP_C7 - RESERVED */\n", + "\tPAD_CFG_NF(GPP_C22, NONE, PLTRST, NF1),", "\t/* UART2_RTS# */", "\n", + "\n\t/* ------- GPIO Group GPP_D ------- */\n", + "\n\t/* ------- GPIO Group GPP_E ------- */\n", + "\tPAD_CFG_NF(GPP_E0, UP_20K, PLTRST, NF1),", "\t/* SATAXPCIE0 */", "\n", + "\n\t/* ------- GPIO Group GPP_G ------- */\n", + "\tPAD_CFG_NF(GPP_G19, NONE, PLTRST, NF1),", "\t/* SMI# */", "\n", + "\n\t/* ------- GPIO Community 2 ------- */\n", + "\n\t/* -------- GPIO Group GPD -------- */\n", + "\tPAD_CFG_NF(GPD9, NONE, PWROK, NF1),", "\t/* SLP_WLAN# */", "\n", + "\n\t/* ------- GPIO Community 3 ------- */\n", + "\n\t/* ------- GPIO Group GPP_I ------- */\n", + "\tPAD_CFG_NF(GPP_I0, NONE, PLTRST, NF1),", "\t/* DDPB_HPD0 */", "\n", + "\tPAD_CFG_NF(GPP_I1, NONE, PLTRST, NF1),", "\t/* DDPC_HPD1 */", "\n", + "\tPAD_CFG_NF(GPP_I2, NONE, PLTRST, NF1),", "\t/* DDPD_HPD2 */", "\n", + } + + input, err := os.Open(testLogFilePath) + if err != nil { + t.Errorf("Something is wrong with the test file - %s!\n", testLogFilePath) + os.Exit(1) + } + defer input.Close() + + config.InputRegDumpFile = input + config.FldStyleSet("none") + config.NonCheckingFlagSet(true) + config.InfoLevelSet(1) + + prs := parser.ParserData{} + prs.Parse() + + printer := Printer{lines: make([]string, 0)} + generator := parser.Generator{ + PrinterIf: &printer, + Data: &prs, + } + + if err := generator.Run(); err != nil { + t.Errorf("Generator: %v", err) + os.Exit(1) + } + + if len(printer.lines) == len(reference) { + for i := range printer.lines { + if printer.lines[i] != reference[i] { + t.Errorf("\nExpects: '%s'\nActually: '%s'\n\n", reference[i], printer.lines[i]) + return + } + } + } else { + t.Errorf("%d does not match the reference slice len - %d!", + len(reference), len(printer.lines)) + } + }) +} diff --git a/util/intelp2m/parser/test/inteltool_test.log b/util/intelp2m/parser/test/inteltool_test.log new file mode 100644 index 0000000..4c01d63 --- /dev/null +++ b/util/intelp2m/parser/test/inteltool_test.log @@ -0,0 +1,55 @@ +CPU: ID 0x906e9, Processor Type 0x0, Family 0x6, Model 0x9e, Stepping 0x9 +Northbridge: 8086:591f (unknown) +Southbridge: 8086:a143 (H110) +IGD: 8086:5912 (Intel(R) UHD Graphics 630) +Trying to reveal Primary to Sideband Bridge (P2SB), +let's hope the OS doesn't mind... done. +SBREG_BAR = 0xfd000000 (MEM) + +Hiding Primary to Sideband Bridge (P2SB). + +============= GPIOS ============= + +------- GPIO Community 0 ------- + +PCR Port ID: 0xaf0000 + +------- GPIO Group GPP_A ------- +0x0400: 0x0000001884000502 GPP_A0 RCIN# +0x0408: 0x0000301984000402 GPP_A1 LAD0 +0x0428: 0x0000001d84000600 GPP_A5 LFRAME# +0x0468: 0x0000002544000600 GPP_A13 SUSWARN#/SUSPWRDNACK +0x04b8: 0x0000002f84000102 GPP_A23 GPIO +------- GPIO Group GPP_B ------- +0x0438: 0xffffffffffffffff GPP_C1 RESERVED +0x04c0: 0x0000003084000100 GPP_B0 GPIO +0x0578: 0x0000104784000a01 GPP_B23 PCHHOT# +------- GPIO Community 1 ------- + +PCR Port ID: 0xae0000 + +------- GPIO Group GPP_C ------- +0x0400: 0x0000004844000502 GPP_C0 SMBCLK +0x0428: 0x0000004d84000100 GPP_C5 GPIO +0x0430: 0xffffffffffffffff GPP_C6 RESERVED +0x0438: 0xffffffffffffffff GPP_C7 RESERVED +0x04b0: 0x0000005e84000600 GPP_C22 UART2_RTS# +------- GPIO Group GPP_D ------- +------- GPIO Group GPP_E ------- +0x0580: 0x0000301884000502 GPP_E0 SATAXPCIE0 +------- GPIO Group GPP_G ------- +0x0740: 0x0000005084000500 GPP_G19 SMI# +------- GPIO Community 2 ------- + +PCR Port ID: 0xad0000 + +-------- GPIO Group GPD -------- +0x0448: 0x0000002104000600 GPD9 SLP_WLAN# +------- GPIO Community 3 ------- + +PCR Port ID: 0xac0000 + +------- GPIO Group GPP_I ------- +0x0400: 0x0000006d84000500 GPP_I0 DDPB_HPD0 +0x0408: 0x0000006e84000502 GPP_I1 DDPC_HPD1 +0x0410: 0x0000006f84000502 GPP_I2 DDPD_HPD2