blob: fbfafda8e967843a9e3b6e7a3ceee1bba091e812 [file] [log] [blame]
// Copyright 2024 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package audio
import (
"context"
"regexp"
"strconv"
"time"
"go.chromium.org/tast/core/errors"
"go.chromium.org/tast/core/testing"
)
func getBits(value uint32, startBit, endBit int) uint32 {
mask := (uint32(1) << (endBit - startBit + 1)) - 1 // Create a mask
return (value >> uint32(startBit)) & mask // Shift and apply the mask
}
func getMEStatus(ctx context.Context, s *testing.FixtState, board string) (uint32, error) {
if board != "Hatch" && board != "Octopus" {
return 0, errors.New("unsupported board")
}
var re *regexp.Regexp
if board == "Hatch" {
// ME: HFSTS1 : 0x90000245
re = regexp.MustCompile(`ME: HFSTS1\s+:\s+(0x[0-9a-fA-F]+)`)
}
if board == "Octopus" {
// CSE FWSTS1: 0x80000045
re = regexp.MustCompile(`CSE FWSTS1:\s+(0x[0-9a-fA-F]+)`)
}
b, err := s.DUT().Conn().CommandContext(ctx, "/usr/bin/cbmem", "-1").Output()
if err != nil {
return 0, errors.Wrap(err, "cbmem -1 failed")
}
match := re.FindStringSubmatch(string(b))
if match == nil {
return 0, errors.New("failed to parse ME status from cbmem -1")
}
hexValue := match[1]
MEStatus, err := strconv.ParseUint(hexValue, 0, 32)
s.Logf("ME status: 0x%X", MEStatus)
return uint32(MEStatus), nil
}
func hasValidMEStatus(ctx context.Context, s *testing.FixtState) bool {
// 'cros_config /identity platform-name' works for Hatch and Octopus, but may return 'Generic' for boards like Brya.
boardInByte, err := s.DUT().Conn().CommandContext(ctx, "cros_config", "/identity", "platform-name").Output()
if err != nil {
// Assume it's valid to reduce the test failure rate.
s.Log("cros_config platform-name failed: ", err)
return true
}
board := string(boardInByte)
s.Logf("board: %s", board)
// b/320175503: GLK/CML devices have un-fixable ME issues.
if board != "Hatch" && board != "Octopus" {
return true
}
MEStatus, err := getMEStatus(ctx, s, board)
if err != nil {
// Assume it's valid until cbmem parsing failure confirms an audio DSP issue.
s.Log("Get MEStatus failed: ", err)
return true
}
if getBits(MEStatus, 0, 3) != 5 || getBits(MEStatus, 12, 15) != 0 {
s.Logf("ME is either not in normal working state: 0x%X or has hit some error: 0x%X", getBits(MEStatus, 0, 3), getBits(MEStatus, 12, 15))
return false
}
return true
}
func init() {
testing.AddFixture(&testing.Fixture{
Name: "rebootForAudioDSPFixture",
Desc: "Reboots the DUT if the Audio DSP failed; Audio test Only; DO NOT USE for other tests",
Contacts: []string{
"judyhsiao@google.com",
"chromeos-audio-sw@google.com",
},
BugComponent: "b:776546",
SetUpTimeout: 5 * time.Minute,
Impl: &rebootForAudioDSPFixtureImpl{},
})
}
type rebootForAudioDSPFixtureImpl struct{}
func (f *rebootForAudioDSPFixtureImpl) SetUp(ctx context.Context, s *testing.FixtState) interface{} {
for reboot := 0; reboot < 2; reboot++ {
if hasValidMEStatus(ctx, s) {
return nil
}
s.Log("Performing cold reset due to invalid ME status")
if err := s.DUT().Conn().CommandContext(ctx, "ectool", "reboot_ec", "cold", "at-shutdown").Run(); err != nil {
s.Fatal("Failed to execute ectool reboot_ec cmd: ", err)
}
if err := s.DUT().Conn().CommandContext(ctx, "shutdown", "-h", "now").Run(); err != nil {
s.Fatal("Failed to execute shutdown command: ", err)
}
if err := s.DUT().WaitConnect(ctx); err != nil {
s.Fatal("Failed to wake up DUT: ", err)
}
}
return nil
}
func (f *rebootForAudioDSPFixtureImpl) TearDown(ctx context.Context, s *testing.FixtState) {
}
func (f *rebootForAudioDSPFixtureImpl) PreTest(ctx context.Context, s *testing.FixtTestState) {
}
func (f *rebootForAudioDSPFixtureImpl) PostTest(ctx context.Context, s *testing.FixtTestState) {
}
func (f *rebootForAudioDSPFixtureImpl) Reset(ctx context.Context) error {
return nil
}