util/hda-decoder: Add feature to print configuration defaults as verbs

This feature simply goes through pin configurations stored in a file and
converts them into their corresponding verbs. This can be useful when
trying to find verb data stored inside a binary (e.g. when reverse
engineering).

Input:
	0x16 0x04211040
	0x17 0x91170110
	0x18 0x40f001f0

Output:
	address: 0, node ID: 0x16, configuration default: 0x04211040
	  0x01671c40
	  0x01671d10
	  0x01671e21
	  0x01671f04
	address: 0, node ID: 0x17, configuration default: 0x91170110
	  0x01771c10
	  0x01771d01
	  0x01771e17
	  0x01771f91
	address: 0, node ID: 0x18, configuration default: 0x40f001f0
	  0x01871cf0
	  0x01871d01
	  0x01871ef0
	  0x01871f40

Change-Id: I1fb74ff4b2b654987fd25ee32d0f94e5f2f783e3
Signed-off-by: Nicholas Sudsgaard <devel+coreboot@nsudsgaard.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/84669
Reviewed-by: Paul Menzel <paulepanter@mailbox.org>
Reviewed-by: Sean Rhodes <sean@starlabs.systems>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Nicholas Sudsgaard 2024-10-05 05:25:51 +00:00 committed by Martin L Roth
commit 33b2fb93bb
3 changed files with 86 additions and 12 deletions

View file

@ -177,3 +177,12 @@ func ToHumanReadable(fields Fields[uint32]) Fields[string] {
Sequence: fmt.Sprintf("%d", fields.Sequence),
}
}
func ConfigToVerbs(address uint32, nodeId uint32, config uint32) [4]uint32 {
return [4]uint32{
(address << 28) | (nodeId << 20) | (0x71c << 8) | ((config >> 0) & 0xff),
(address << 28) | (nodeId << 20) | (0x71d << 8) | ((config >> 8) & 0xff),
(address << 28) | (nodeId << 20) | (0x71e << 8) | ((config >> 16) & 0xff),
(address << 28) | (nodeId << 20) | (0x71f << 8) | ((config >> 24) & 0xff),
}
}

View file

@ -107,3 +107,42 @@ func TestToHumanReadable(t *testing.T) {
}
}
}
type configToVerbsTest struct {
arg1 uint32
arg2 uint32
arg3 uint32
expected [4]uint32
}
var configToVerbsTests = []configToVerbsTest{
configToVerbsTest{
0, 0x19, 0x1cc3efde,
[4]uint32{0x01971cde, 0x01971def, 0x01971ec3, 0x01971f1c},
},
configToVerbsTest{
9, 0x4e, 0x913ddc4c,
[4]uint32{0x94e71c4c, 0x94e71ddc, 0x94e71e3d, 0x94e71f91},
},
configToVerbsTest{
12, 0xf4, 0x4193db3a,
[4]uint32{0xcf471c3a, 0xcf471ddb, 0xcf471e93, 0xcf471f41},
},
configToVerbsTest{
7, 0xb7, 0x0c39e09a,
[4]uint32{0x7b771c9a, 0x7b771de0, 0x7b771e39, 0x7b771f0c},
},
configToVerbsTest{
3, 0x5a, 0x24c04c66,
[4]uint32{0x35a71c66, 0x35a71d4c, 0x35a71ec0, 0x35a71f24},
},
}
func TestConfigToVerbs(t *testing.T) {
for _, test := range configToVerbsTests {
output := ConfigToVerbs(test.arg1, test.arg2, test.arg3)
if output != test.expected {
t.Errorf("Expected %#08x, received %#08x", test.expected, output)
}
}
}

View file

@ -14,6 +14,13 @@ import (
"strings"
)
type decodeOperation int
const (
decodeToHumanReadable decodeOperation = iota
decodeToVerbs
)
var indentLevel int = 0
func indentedPrintf(format string, args ...interface{}) (n int, err error) {
@ -58,7 +65,7 @@ func printDisconnectedPort(config uint32) {
}
}
func decodeFile(path string, codec uint32) {
func decodeFile(path string, codec uint32, operation decodeOperation) {
file, err := os.Open(path)
if err != nil {
log.Fatal(err)
@ -77,15 +84,27 @@ func decodeFile(path string, codec uint32) {
pin := stringToUint32(fields[0])
config := stringToUint32(fields[1])
indentedPrintf("AZALIA_PIN_CFG(%d, 0x%02x, ", codec, pin)
if decoder.PortIsConnected(config) {
fmt.Printf("AZALIA_PIN_DESC(\n")
indentLevel += 1
decodeConfig(config)
indentLevel -= 1
indentedPrintf(")),\n")
} else {
printDisconnectedPort(config)
switch operation {
case decodeToVerbs:
fmt.Printf("address: %d, node ID: %#02x, configuration default: %#08x\n",
codec, pin, config)
verbs := decoder.ConfigToVerbs(codec, pin, config)
fmt.Printf(" %#08x\n", verbs[0])
fmt.Printf(" %#08x\n", verbs[1])
fmt.Printf(" %#08x\n", verbs[2])
fmt.Printf(" %#08x\n", verbs[3])
case decodeToHumanReadable:
indentedPrintf("AZALIA_PIN_CFG(%d, 0x%02x, ", codec, pin)
if decoder.PortIsConnected(config) {
fmt.Printf("AZALIA_PIN_DESC(\n")
indentLevel += 1
decodeConfig(config)
indentLevel -= 1
indentedPrintf(")),\n")
} else {
printDisconnectedPort(config)
}
}
}
}
@ -116,7 +135,7 @@ func decodeDeviceCodec(path string, codec uint32, isLastCodec bool, generate boo
indentedPrintf("AZALIA_SUBVENDOR(%d, %s),\n\n", codec, subsystemId)
}
decodeFile(path+"/init_pin_configs", codec)
decodeFile(path+"/init_pin_configs", codec, decodeToHumanReadable)
if !isLastCodec {
fmt.Printf("\n")
}
@ -155,12 +174,19 @@ func main() {
file := flag.String("file", "", "Decode configurations in a file\n"+
"The decoder assumes each line in the file has the format: <pin> <config>")
generate := flag.Bool("generate", false, "Automatically generate hda_verb.c for the host device")
toVerbs := flag.Bool("to-verbs", false, "Convert configuration defaults to their corresponding verbs\n"+
"This flag is only meaningful in combination with the 'file' flag")
flag.Parse()
operation := decodeToHumanReadable
if *toVerbs {
operation = decodeToVerbs
}
if isFlagPassed("config") {
decodeConfig(uint32(*config))
} else if isFlagPassed("file") {
decodeFile(*file, uint32(*codec))
decodeFile(*file, uint32(*codec), operation)
} else {
if *generate {
fmt.Printf("/* SPDX-License-Identifier: GPL-2.0-only */\n\n")