blob: 2c8e722ce45a1d282535601dad41cbfab4dd10d2 [file] [log] [blame]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package gscdevboard
import (
"bytes"
"context"
"time"
"go.chromium.org/tast-tests/cros/common/firmware/ti50"
"go.chromium.org/tast-tests/cros/remote/bundles/cros/gscdevboard/utils"
"go.chromium.org/tast-tests/cros/remote/firmware/ti50/fixture"
"go.chromium.org/tast/core/testing"
)
type cCDCapabilitiesFlashEC struct {
capState ti50.CCDCapState
expectInterfaceOpenWhenCCDLocked bool
}
func init() {
testing.AddTest(&testing.Test{
Func: CCDCapabilitiesFlashEC,
Desc: "Test the FlashEC CCD capability controls flashing the EC with I2C and SPI",
Timeout: 30 * time.Second,
Contacts: []string{
"gsc-sheriff@google.com", // CrOS GSC Developers
},
BugComponent: "b:715469", // ChromeOS > Platform > System > Hardware Security > HwSec GSC > Ti50
Attr: []string{"group:gsc", "gsc_dt_ab", "gsc_dt_shield", "gsc_image_ti50", "gsc_nightly"},
Fixture: fixture.GSCOpenCCD,
Params: []testing.Param{{
Name: "cap_default",
Val: cCDCapabilitiesFlashEC{
capState: ti50.CapDefault,
expectInterfaceOpenWhenCCDLocked: false,
},
}, {
Name: "cap_always",
Val: cCDCapabilitiesFlashEC{
capState: ti50.CapAlways,
expectInterfaceOpenWhenCCDLocked: true,
},
}, {
Name: "cap_if_opened",
Val: cCDCapabilitiesFlashEC{
capState: ti50.CapIfOpened,
expectInterfaceOpenWhenCCDLocked: false,
},
}},
// TODO(b:240149552): Add `cap_unless_locked` test for Cr50 only
})
}
func CCDCapabilitiesFlashEC(ctx context.Context, s *testing.State) {
userParams := s.Param().(cCDCapabilitiesFlashEC)
b := utils.NewDevboardHelper(s)
i := ti50.MustOpenCrOSImage(ctx, b, s)
defer i.Close(ctx)
b.GpioApplyStrap(ctx, ti50.CcdSuzyQ)
_ = b.ResetAndTpmStartup(ctx, i, ti50.CcdSuzyQ, ti50.FfClamshell)
b.WaitUntilCCDConnected(ctx)
// Set capabilities into their correct states
if err := i.CCDOpen(ctx); err != nil {
s.Fatal("Failed to open CCD: ", err)
}
ccdStates := map[ti50.CCDCap]ti50.CCDCapState{
ti50.FlashAP: ti50.CapAlways,
ti50.FlashEC: userParams.capState,
}
if err := i.SetCCDCapabilities(ctx, ccdStates); err != nil {
s.Fatal("Failed to set CCD open related capabilities: ", err)
}
// Make sure we disable the SPI bridge at the end of the test
defer b.GscUsbSpiBridge(ctx, ti50.DisableSpiBridge)
// Perform a read, right before the ITE waveform, and ensure that response
// size of ITE waveform request is correct (See b/322166906)
verifyI2CRead(ctx, s, &b)
verifyIteSyncCommand(ctx, s, &b, true)
verifyEcSpiBridgeEnable(ctx, s, &b, true)
verifySpiBridgeState(ctx, s, &b, true)
b.GscUsbSpiBridge(ctx, ti50.DisableSpiBridge)
if err := i.CCDLock(ctx); err != nil {
s.Fatal("Failed to lock CCD: ", err)
}
verifyIteSyncCommand(ctx, s, &b, userParams.expectInterfaceOpenWhenCCDLocked)
verifyEcSpiBridgeEnable(ctx, s, &b, userParams.expectInterfaceOpenWhenCCDLocked)
verifySpiBridgeState(ctx, s, &b, userParams.expectInterfaceOpenWhenCCDLocked)
// TODO(b:240149552): Test the EC UART bridge?
}
func verifyIteSyncCommand(ctx context.Context, s *testing.State, b *utils.DevboardHelper, expectSuccess bool) {
// Special ITE sync command
requestData := []byte{0, 0x78, 1, 0, 0}
response, err := b.GscUsbI2cInterfaceTransaction(ctx, requestData)
if err != nil {
s.Fatalf("Got error: %s", err)
}
// ITE sync responses
expectedResponse := []byte{0, 0, 0, 0}
if !expectSuccess {
expectedResponse = []byte{6, 0, 0, 0}
}
if !bytes.Equal(expectedResponse, response) {
s.Errorf("Expected ITE I2C interface response %v, but got %v", expectedResponse, response)
}
}
func verifyI2CRead(ctx context.Context, s *testing.State, b *utils.DevboardHelper) {
// Read address 0x60 for 2 bytes. There is nothing at 0x60, so we should
// get a timeout error.
requestData := []byte{0, 0x60, 0, 2}
response, err := b.GscUsbI2cInterfaceTransaction(ctx, requestData)
if err != nil {
s.Fatalf("Got error: %s", err)
}
// Expected Timeout failure response
expectedResponse := []byte{1, 0, 0, 0, 0, 0}
if !bytes.Equal(expectedResponse, response) {
s.Errorf("Expected I2C interface response %v, but got %v", expectedResponse, response)
}
}
func verifyEcSpiBridgeEnable(ctx context.Context, s *testing.State, b *utils.DevboardHelper, expectSuccess bool) {
err := b.GscUsbSpiBridge(ctx, ti50.EnableEcSpiBridge)
if expectSuccess {
if err != nil {
s.Error("Failed to enable the EC SPI bridge when we expected success: ", err)
}
} else {
if err == nil {
s.Error("Enabled the EC SPI bridge when we expected failure")
}
}
}
func verifySpiBridgeState(ctx context.Context, s *testing.State, b *utils.DevboardHelper, expectSuccess bool) {
// SPI bridge get configuration packet request
requestData := []byte{0, 0} // Get configuration packet request
response, err := b.GscUsbSpiInterfaceTransaction(ctx, requestData)
if expectSuccess {
// Expect an 8 byte response on success, we don't care about the content.
if err != nil {
s.Error("Failed to get the USB SPI configuration response: ", err)
} else if len(response) != 8 {
s.Error("Expected SPI bridge response of 8B, but got ", response)
}
} else {
// We get a USB error if the bridge is disabled
if err == nil {
s.Error("Expected SPI interface to be disabled, but was able to successfully transact")
}
}
}