Merge "Test V4 apk_digest computation in apkverify"
diff --git a/libs/apkverify/src/v3.rs b/libs/apkverify/src/v3.rs
index bad6bc2..7533b3b 100644
--- a/libs/apkverify/src/v3.rs
+++ b/libs/apkverify/src/v3.rs
@@ -16,9 +16,6 @@
 
 //! Verifies APK Signature Scheme V3
 
-// TODO(jooyung) remove this
-#![allow(dead_code)]
-
 use anyhow::{anyhow, bail, ensure, Context, Result};
 use bytes::Bytes;
 use openssl::hash::MessageDigest;
@@ -63,6 +60,7 @@
     certificates: LengthPrefixed<Vec<LengthPrefixed<X509Certificate>>>,
     min_sdk: u32,
     max_sdk: u32,
+    #[allow(dead_code)]
     additional_attributes: LengthPrefixed<Vec<LengthPrefixed<AdditionalAttributes>>>,
 }
 
diff --git a/microdroid/initrd/Android.bp b/microdroid/initrd/Android.bp
new file mode 100644
index 0000000..147c963
--- /dev/null
+++ b/microdroid/initrd/Android.bp
@@ -0,0 +1,13 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_binary_host {
+    name: "initrd_bootconfig",
+    srcs: ["src/main.rs"],
+    rustlibs: [
+        "libanyhow",
+        "libstructopt",
+    ],
+    prefer_rlib: true,
+}
diff --git a/microdroid/initrd/src/main.rs b/microdroid/initrd/src/main.rs
new file mode 100644
index 0000000..1023a40
--- /dev/null
+++ b/microdroid/initrd/src/main.rs
@@ -0,0 +1,77 @@
+// Copyright 2022, 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.
+
+//! Append bootconfig to initrd image
+use anyhow::Result;
+
+use std::fs::File;
+use std::io::{Read, Write};
+use std::path::PathBuf;
+use structopt::StructOpt;
+
+const FOOTER_ALIGNMENT: usize = 4;
+const ZEROS: [u8; 4] = [0u8; 4_usize];
+
+#[derive(StructOpt, Debug)]
+struct Args {
+    /// Output
+    #[structopt(parse(from_os_str), long = "output")]
+    output: PathBuf,
+    /// Initrd (without bootconfig)
+    #[structopt(parse(from_os_str))]
+    initrd: PathBuf,
+    /// Bootconfig
+    #[structopt(parse(from_os_str))]
+    bootconfigs: Vec<PathBuf>,
+}
+
+fn get_checksum(file_path: &PathBuf) -> Result<u32> {
+    File::open(file_path)?.bytes().map(|x| Ok(x? as u32)).sum()
+}
+
+// Bootconfig is attached to the initrd in the following way:
+// [initrd][bootconfig][padding][size(le32)][checksum(le32)][#BOOTCONFIG\n]
+fn attach_bootconfig(initrd: PathBuf, bootconfigs: Vec<PathBuf>, output: PathBuf) -> Result<()> {
+    let mut output_file = File::create(&output)?;
+    let mut initrd_file = File::open(&initrd)?;
+    let initrd_size: usize = initrd_file.metadata()?.len().try_into()?;
+    let mut bootconfig_size: usize = 0;
+    let mut checksum: u32 = 0;
+
+    std::io::copy(&mut initrd_file, &mut output_file)?;
+    for bootconfig in bootconfigs {
+        let mut bootconfig_file = File::open(&bootconfig)?;
+        std::io::copy(&mut bootconfig_file, &mut output_file)?;
+        bootconfig_size += bootconfig_file.metadata()?.len() as usize;
+        checksum += get_checksum(&bootconfig)?;
+    }
+
+    let padding_size: usize = FOOTER_ALIGNMENT - (initrd_size + bootconfig_size) % FOOTER_ALIGNMENT;
+    output_file.write_all(&ZEROS[..padding_size])?;
+    output_file.write_all(&((padding_size + bootconfig_size) as u32).to_le_bytes())?;
+    output_file.write_all(&checksum.to_le_bytes())?;
+    output_file.write_all(b"#BOOTCONFIG\n")?;
+    output_file.flush()?;
+    Ok(())
+}
+
+fn try_main() -> Result<()> {
+    let args = Args::from_args_safe()?;
+    attach_bootconfig(args.initrd, args.bootconfigs, args.output)?;
+    Ok(())
+}
+
+fn main() {
+    try_main().unwrap()
+}
diff --git a/pvmfw/Android.bp b/pvmfw/Android.bp
index eab9474..5bcafd5 100644
--- a/pvmfw/Android.bp
+++ b/pvmfw/Android.bp
@@ -15,8 +15,7 @@
 }
 
 cc_binary {
-    name: "pvmfw_elf",
-    stem: "pvmfw",
+    name: "pvmfw",
     defaults: ["vmbase_elf_defaults"],
     srcs: [
         "idmap.S",
@@ -33,8 +32,9 @@
 }
 
 raw_binary {
-    name: "pvmfw",
-    src: ":pvmfw_elf",
+    name: "pvmfw_bin",
+    stem: "pvmfw.bin",
+    src: ":pvmfw",
     enabled: false,
     target: {
         android_arm64: {
diff --git a/pvmfw/src/exceptions.rs b/pvmfw/src/exceptions.rs
index 0e637ac..596ecc7 100644
--- a/pvmfw/src/exceptions.rs
+++ b/pvmfw/src/exceptions.rs
@@ -19,8 +19,9 @@
 
 #[no_mangle]
 extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) {
+    let esr = read_esr();
     emergency_write_str("sync_exception_current\n");
-    print_esr();
+    print_esr(esr);
     reboot();
 }
 
@@ -38,15 +39,17 @@
 
 #[no_mangle]
 extern "C" fn serr_current(_elr: u64, _spsr: u64) {
+    let esr = read_esr();
     emergency_write_str("serr_current\n");
-    print_esr();
+    print_esr(esr);
     reboot();
 }
 
 #[no_mangle]
 extern "C" fn sync_lower(_elr: u64, _spsr: u64) {
+    let esr = read_esr();
     emergency_write_str("sync_lower\n");
-    print_esr();
+    print_esr(esr);
     reboot();
 }
 
@@ -64,16 +67,22 @@
 
 #[no_mangle]
 extern "C" fn serr_lower(_elr: u64, _spsr: u64) {
+    let esr = read_esr();
     emergency_write_str("serr_lower\n");
-    print_esr();
+    print_esr(esr);
     reboot();
 }
 
 #[inline]
-fn print_esr() {
+fn read_esr() -> u64 {
     let mut esr: u64;
     unsafe {
         asm!("mrs {esr}, esr_el1", esr = out(reg) esr);
     }
+    esr
+}
+
+#[inline]
+fn print_esr(esr: u64) {
     eprintln!("esr={:#08x}", esr);
 }
diff --git a/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
index c9ceaae..7bf3c4e 100644
--- a/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
+++ b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
@@ -143,11 +143,7 @@
 
             // To grab boot events from log, set debug mode to FULL
             VirtualMachineConfig normalConfig =
-                    builder.debugLevel(DebugLevel.FULL)
-                            .memoryMib(256)
-                            .numCpus(2)
-                            .cpuAffinity("0=0:1=1")
-                            .build();
+                    builder.debugLevel(DebugLevel.FULL).memoryMib(256).build();
             mInner.forceCreateNewVirtualMachine("test_vm_boot_time", normalConfig);
 
             BootResult result = tryBootVm(TAG, "test_vm_boot_time");
@@ -194,8 +190,6 @@
         VirtualMachineConfig config =
                 mInner.newVmConfigBuilder("assets/vm_config_io.json")
                         .debugLevel(DebugLevel.FULL)
-                        .numCpus(2)
-                        .cpuAffinity("0=0:1=1")
                         .build();
         List<Double> transferRates = new ArrayList<>(IO_TEST_TRIAL_COUNT);
 
@@ -223,8 +217,6 @@
         VirtualMachineConfig config =
                 mInner.newVmConfigBuilder("assets/vm_config_io.json")
                         .debugLevel(DebugLevel.FULL)
-                        .numCpus(2)
-                        .cpuAffinity("0=0:1=1")
                         .build();
         List<Double> readRates = new ArrayList<>(IO_TEST_TRIAL_COUNT);
 
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
index d86f2bf..a6b228d 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
@@ -68,11 +68,15 @@
      * Comma-separated list of CPUs or CPU ranges to run vCPUs on (e.g. 0,1-3,5), or
      * colon-separated list of assignments of vCPU to host CPU assignments (e.g. 0=0:1=1:2=2).
      * Default is no mask which means a vCPU can run on any host CPU.
+     *
+     * Note: Using a non-null value requires android.permission.USE_CUSTOM_VIRTUAL_MACHINE.
      */
     @nullable String cpuAffinity;
 
     /**
      * List of task profile names to apply for the VM
+     *
+     * Note: Specifying a value here requires android.permission.USE_CUSTOM_VIRTUAL_MACHINE.
      */
     String[] taskProfiles;
 }
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index 352b4f1..dcc2d48 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -596,6 +596,12 @@
     config: &VirtualMachineAppConfig,
     temporary_directory: &Path,
 ) -> Result<VirtualMachineRawConfig> {
+    // Controlling CPUs is reserved for platform apps only, even when using
+    // VirtualMachineAppConfig.
+    if config.cpuAffinity.is_some() || !config.taskProfiles.is_empty() {
+        check_use_custom_virtual_machine()?
+    }
+
     let apk_file = clone_file(config.apk.as_ref().unwrap())?;
     let idsig_file = clone_file(config.idsig.as_ref().unwrap())?;
     let instance_file = clone_file(config.instanceImage.as_ref().unwrap())?;
diff --git a/vmbase/Android.bp b/vmbase/Android.bp
index ab87053..fb525b5 100644
--- a/vmbase/Android.bp
+++ b/vmbase/Android.bp
@@ -49,6 +49,13 @@
         "libarm-optimized-routines-mem",
         "libvmbase_entry",
     ],
+    installable: false,
+    enabled: false,
+    target: {
+        android_arm64: {
+            enabled: true,
+        },
+    },
 }
 
 rust_library_rlib {
diff --git a/vmbase/example/Android.bp b/vmbase/example/Android.bp
index e11bb2f..4e62090 100644
--- a/vmbase/example/Android.bp
+++ b/vmbase/example/Android.bp
@@ -18,8 +18,7 @@
 }
 
 cc_binary {
-    name: "vmbase_example_elf",
-    stem: "vmbase_example",
+    name: "vmbase_example",
     defaults: ["vmbase_elf_defaults"],
     srcs: [
         "idmap.S",
@@ -35,8 +34,9 @@
 }
 
 raw_binary {
-    name: "vmbase_example",
-    src: ":vmbase_example_elf",
+    name: "vmbase_example_bin",
+    stem: "vmbase_example.bin",
+    src: ":vmbase_example",
     enabled: false,
     target: {
         android_arm64: {
@@ -60,7 +60,7 @@
         "libvmclient",
     ],
     data: [
-        ":vmbase_example",
+        ":vmbase_example_bin",
     ],
     test_suites: ["general-tests"],
     enabled: false,