blob: 0f301a4bbc0a2887835c1df8983fc90b0d84c61c [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tradefed.targetprep;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.build.KernelDeviceBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.DeviceUnresponsiveException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.util.CommandResult;
import com.android.tradefed.util.CommandStatus;
import com.android.tradefed.util.FileUtil;
import com.android.tradefed.util.IRunUtil;
import com.android.tradefed.util.RunUtil;
import java.io.File;
import java.io.IOException;
/**
* A {@link ITargetPreparer} that flashes a kernel on the device.
*/
public class KernelFlashPreparer implements ITargetPreparer {
/**
* {@inheritDoc}
* <p>
* Expects a {@link KernelDeviceBuildInfo} that returns non-null values for
* {@link KernelDeviceBuildInfo#getMkbootimgFile()} and
* {@link KernelDeviceBuildInfo#getRamdiskFile()}.
* </p>
*/
@Override
public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
BuildError, DeviceNotAvailableException {
if (!(buildInfo instanceof KernelDeviceBuildInfo)) {
throw new IllegalArgumentException("Provided buildInfo is not a KernelDeviceBuildInfo");
}
KernelDeviceBuildInfo kernelBuildInfo = (KernelDeviceBuildInfo) buildInfo;
CLog.i("Flashing device %s running %s with kernel %s", device.getSerialNumber(),
device.getBuildId(), kernelBuildInfo.getSha1());
if (kernelBuildInfo.getRamdiskFile() == null) {
throw new TargetSetupError("Missing ramdisk file");
}
if (kernelBuildInfo.getMkbootimgFile() == null) {
throw new TargetSetupError("Missing mkbootimg file");
}
if (kernelBuildInfo.getKernelFile() == null) {
throw new TargetSetupError("Missing kernel file");
}
kernelBuildInfo.getMkbootimgFile().setExecutable(true);
File boot = null;
try {
boot = createBootImage(kernelBuildInfo.getMkbootimgFile(),
kernelBuildInfo.getKernelFile(), kernelBuildInfo.getRamdiskFile());
} catch (IOException e) {
throw new TargetSetupError("Could not create boot image", e);
}
try {
device.rebootIntoBootloader();
CLog.d("fastboot flash boot %s", boot.getAbsolutePath());
device.executeFastbootCommand("flash", "boot", boot.getAbsolutePath());
} finally {
FileUtil.deleteFile(boot);
}
try {
device.reboot();
} catch (DeviceUnresponsiveException e) {
// assume this is a build problem
throw new BuildError(String.format("Device %s did not become available after " +
"flashing kernel", device.getSerialNumber()));
}
device.postBootSetup();
}
/**
* Creates a boot.img file using mkbootimg, ramdisk, and kernel files.
* <p>
* Runs {@code mkbootimg --kernel (filename) --ramdisk (filename) -o (filename)} to create a
* boot.img image file. Exposed for unit testing.
* </p>
*
* @param mkbootimg the mkbootimg executable
* @param kernel the kernel file
* @param ramdisk the ramdisk file
* @return a boot.img {@link File} for the build and kernel build
* @throws IOException if there was an exception making the boot image
*/
File createBootImage(File mkbootimg, File kernel, File ramdisk) throws IOException {
CLog.d("Create boot.img from %s and %s", kernel.getAbsolutePath(),
ramdisk.getAbsolutePath());
String bootPath = getBootImgPath();
try {
String[] cmd = {mkbootimg.getAbsolutePath(), "--kernel", kernel.getAbsolutePath(),
"--ramdisk", ramdisk.getAbsolutePath(), "-o", bootPath};
CommandResult result = getRunUtil().runTimedCmd(30 * 1000, cmd);
if (result.getStatus() != CommandStatus.SUCCESS) {
CLog.e("mkbootimg failed. Command status was %s", result.getStatus());
FileUtil.deleteFile(new File(bootPath));
throw new IOException();
}
} catch (IOException e) {
FileUtil.deleteFile(new File(bootPath));
throw e;
} catch (RuntimeException e) {
FileUtil.deleteFile(new File(bootPath));
throw e;
}
return new File(bootPath);
}
/**
* Get an {@link IRunUtil} instance. Exposed for unit testing.
*/
IRunUtil getRunUtil() {
return RunUtil.getDefault();
}
/**
* Create a path for the boot image using {@link FileUtil#createTempFile(String, String)}.
* Exposed for unit testing.
*/
String getBootImgPath() throws IOException {
File bootImg = FileUtil.createTempFile("boot", ".img");
String bootImgPath = bootImg.getAbsolutePath();
FileUtil.deleteFile(bootImg);
return bootImgPath;
}
}