blob: a9a4c8e208f95f29752f1e90a738b335858e202e [file] [log] [blame]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// First step of FirmwareService State Machine. Installs RW firmware.
package state_machine
import (
firmwareservice "go.chromium.org/chromiumos/test/provision/v2/cros-fw-provision/service"
"context"
"fmt"
"log"
"go.chromium.org/chromiumos/config/go/test/api"
)
// FirmwareUpdateRoState updates firmware with write protection disabled.
type FirmwareUpdateRoState struct {
service *firmwareservice.FirmwareService
}
// Execute flashes firmware with write-protection disabled using futility.
func (s FirmwareUpdateRoState) Execute(ctx context.Context, log *log.Logger) (*api.FirmwareProvisionResponse, api.InstallResponse_Status, error) {
connection := s.service.GetConnectionToFlashingDevice()
// form futility command args based on the request
var futilityImageArgs []string
// Detailed Request
var mainRoPath string
var err error
mainRoMetadata, ok := s.service.GetImageMetadata(s.service.GetMainRoPath())
if ok {
log.Printf("[FW Provisioning: Update RO] extracting AP image to flash\n")
mainRoPath, err = firmwareservice.PickAndExtractMainImage(ctx, connection, mainRoMetadata, s.service.GetMainRoPath(), s.service)
if err != nil {
return nil, api.InstallResponse_STATUS_UPDATE_FIRMWARE_FAILED, firmwareservice.UpdateFirmwareFailedErr(err)
}
futilityImageArgs = append(futilityImageArgs, []string{fmt.Sprint("--image=", mainRoPath)}...)
}
ecRoMetadata, ok := s.service.GetImageMetadata(s.service.GetEcRoPath())
if ok {
log.Printf("[FW Provisioning: Update RO] extracting EC image to flash\n")
ecRoPath, err := firmwareservice.PickAndExtractECImage(ctx, connection, ecRoMetadata, s.service.GetEcRoPath(), s.service)
if err != nil {
return nil, api.InstallResponse_STATUS_UPDATE_FIRMWARE_FAILED, firmwareservice.UpdateFirmwareFailedErr(err)
}
if s.service.IsServoUsed() {
log.Printf("[FW Provisioning: Update RO] separately flashing EC over Servo with flash_ec\n")
// futility refuses to flash EC over servod as a separate image and only
// accepts single image: http://shortn/_dtaO92HvqW. So, for servod, we
// use flash_ec script that to flash the EC separately.
flashECScript, err := firmwareservice.GetFlashECScript(ctx, connection, ecRoMetadata.ArchiveDir)
if err != nil {
return nil, api.InstallResponse_STATUS_UPDATE_FIRMWARE_FAILED, firmwareservice.UpdateFirmwareFailedErr(err)
}
err = s.service.ProvisionWithFlashEC(ctx, ecRoPath, flashECScript)
if err != nil {
return nil, api.InstallResponse_STATUS_UPDATE_FIRMWARE_FAILED, firmwareservice.UpdateFirmwareFailedErr(err)
}
} else {
// For SSH, we can simply run `futility ... --ec-image=$EC_IMAGE ...`
futilityImageArgs = append(futilityImageArgs, []string{fmt.Sprint("--ec_image=", ecRoPath)}...)
}
}
log.Printf("[FW Provisioning: Update RO] flashing RO firmware with futility\n")
err = s.service.FlashWithFutility(ctx, false /* WP */, futilityImageArgs, mainRoPath)
if err != nil {
return nil, api.InstallResponse_STATUS_UPDATE_FIRMWARE_FAILED, firmwareservice.UpdateFirmwareFailedErr(err)
}
return nil, api.InstallResponse_STATUS_SUCCESS, nil
}
func (s FirmwareUpdateRoState) Next() ServiceState {
if s.service.UpdateRw() {
return FirmwareUpdateRwState(s)
} else {
return FirmwarePostInstallState(s)
}
}
const UpdateRoStateName = "Firmware Update RO"
func (s FirmwareUpdateRoState) Name() string {
return UpdateRoStateName
}