Android Emulator Development, Anbox, & Waydroid

Extending Android Emulator UEFI with Custom Shell Commands and Applications

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction

The Android Emulator, a cornerstone tool for application development, typically leverages QEMU to virtualize ARM or x86 architectures. A crucial, often overlooked, component of this virtualization stack is the Unified Extensible Firmware Interface (UEFI) firmware. While typically a black box, understanding and extending the UEFI layer opens up powerful avenues for advanced debugging, custom bootloader development, and integrating specialized system-level applications directly into the emulator’s boot process.

This article provides an expert-level guide to dissecting, modifying, and integrating custom UEFI applications and shell commands within the Android Emulator’s UEFI environment. We will delve into obtaining the firmware, setting up the EDK2 development environment, crafting a bespoke UEFI application, and finally, deploying it to influence the emulator’s boot sequence. This knowledge is invaluable for those looking to build custom Android distributions, develop low-level system utilities, or gain deeper insights into the Android boot chain.

Understanding Android Emulator UEFI

The Android Emulator uses QEMU, which, for modern Android Virtual Devices (AVDs), boots via a UEFI firmware image. This image is usually an adaptation of the Open Virtual Machine Firmware (OVMF) project, itself part of the broader EDK2 (EFI Development Kit II) framework. EDK2 is Intel’s open-source reference implementation of the UEFI standard.

When you launch an Android AVD, QEMU loads this UEFI firmware from a file, often named firmware.img or similar. This firmware is responsible for initializing the virtual hardware, providing a boot manager, and eventually launching the Android kernel. The UEFI Shell, an optional component of EDK2, offers a command-line interface within the firmware environment, allowing for diagnostics, file manipulation, and launching UEFI applications (.efi files).

Key Components:

  • QEMU: The virtualization hypervisor.
  • EDK2/OVMF: The open-source UEFI firmware implementation.
  • firmware.img: The compiled UEFI image provided with the Android SDK.
  • UEFI Shell: A powerful command-line interface within UEFI.

Prerequisites

To follow along with this guide, you will need:

  • A Linux development environment (Ubuntu/Debian recommended).
  • Basic familiarity with C/C++ programming.
  • An AOSP build environment (or at least the necessary tools for EDK2 compilation).
  • A working Android Emulator setup.

Step 1: Obtaining and Inspecting the UEFI Firmware

The first step is to locate the UEFI firmware used by your Android Emulator. It’s typically found within the Android SDK installation.

find $ANDROID_SDK_ROOT -name "firmware.img"

A common path might be $ANDROID_SDK_ROOT/emulator/qemu/linux-x86_64/firmware.img (adjust for your OS/architecture). This firmware.img is a raw UEFI flash image containing multiple firmware volumes (FVs).

You can inspect its structure using tools like uefi-firmware-parser or binwalk:

binwalk -M firmware.img

This will reveal the various PE/COFF images, EFI modules, and other components embedded within the firmware.

Step 2: Setting Up EDK2 for Custom Builds

To extend the UEFI firmware, we’ll need to build our own using the EDK2 source. This allows us to inject custom applications.

2.1 Clone EDK2

git clone https://github.com/tianocore/edk2.gitedk2-platforms/git clone https://github.com/tianocore/edk2-platforms.gitcd edk2

2.2 Initialize EDK2 Environment

EDK2 requires a specific environment setup to compile its various packages.

git submodule update --init --recursive./edksetup.sh

You might need to install build dependencies:

sudo apt-get install build-essential uuid-dev nasm acpica-tools python3-distutils

2.3 Building OVMF

We’ll target the OvmfPkg, which is the QEMU/KVM virtual machine firmware package. OVMF typically includes a UEFI shell.

build -p OvmfPkg/OvmfPkg.dsc -a X64 -t GCC5 -b DEBUG -D SECURE_BOOT_ENABLE

This command builds the OVMF firmware for a 64-bit architecture using GCC5 with debug symbols and secure boot enabled (optional). The output files, including OVMF.fd (which functions similarly to firmware.img), will be located in Build/OvmfX64/DEBUG_GCC5/FV/.

Step 3: Creating a Custom UEFI Application (Hello World)

Now, let’s create a simple UEFI application that prints a message.

3.1 Create a new package and application directory

Inside your edk2 directory, create a new package (e.g., MyUefiPkg) and an application directory:

mkdir -p MyUefiPkg/MyHelloWorldApp

3.2 Create the INF file (MyHelloWorldApp.inf)

This file describes your application to the EDK2 build system.

# MyUefiPkg/MyHelloWorldApp/MyHelloWorldApp.inf[Defines]  INF_VERSION                    = 0x00010005  BASE_NAME                      = MyHelloWorldApp  FILE_GUID                      = 5092A676-4F7F-4B9E-8A51-2C6F8E8F59C4  MODULE_TYPE                    = UEFI_APPLICATION  VERSION_STRING                 = 1.0  ENTRY_POINT                    = UefiMain[Sources]  MyHelloWorldApp.c[Packages]  MdePkg/MdePkg.dec[LibraryClasses]  UefiApplicationEntryPoint  UefiLib[Guids][Pcd]

3.3 Create the C source file (MyHelloWorldApp.c)

This is your actual application code.

#include <Uefi.h>#include <Library/UefiLib.h>#include <Library/UefiApplicationEntryPoint.h>EFI_STATUSEFIAPIUefiMain (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable){  Print(L"Hello from Custom UEFI Application in Android Emulator!n");  return EFI_SUCCESS;}

3.4 Integrate into EDK2 Build System

To make EDK2 aware of your application, you need to add it to a DSC (Driver SConsolidator) file. For OVMF, this is usually OvmfPkg/OvmfPkg.dsc. First, add your package to the main workspace file (e.g., Conf/Target.txt or create a new file like Conf/UserPackages.fdf and include it).

Add your application’s path to OvmfPkg/OvmfPkg.dsc in the [Components] section:

[Components]  ...  MyUefiPkg/MyHelloWorldApp/MyHelloWorldApp.inf

Now, rebuild OVMF:

build -p OvmfPkg/OvmfPkg.dsc -a X64 -t GCC5 -b DEBUG -D SECURE_BOOT_ENABLE

Your MyHelloWorldApp.efi will be created in the build directory, typically Build/OvmfX64/DEBUG_GCC5/X64/MyHelloWorldApp.efi.

Step 4: Integrating Custom Application into Android Emulator Boot

We have our custom OVMF image with the application. Now, we need to make the Android Emulator use it.

4.1 Replace the Firmware Image

Copy your newly built OVMF.fd to the emulator’s firmware location, renaming it to firmware.img.

cp Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd $ANDROID_SDK_ROOT/emulator/qemu/linux-x86_64/firmware.img

Important: Backup the original firmware.img first!

4.2 Launching from UEFI Shell

When you start your AVD, QEMU will now boot your custom UEFI firmware. If the UEFI Shell is configured to be the primary boot option (which is common in OVMF debug builds), you will land directly in the shell. From there, you can execute your application:

Shell> fs0:Shell> MyHelloWorldApp.efi

You should see

Android Mobile Specs & Compare Directory

Are you researching mobile hardware properties, processor SoCs, GPU chipsets, or RAM configurations? Access our complete specs catalog to compare up to 5 devices side-by-side!

Compare Devices Specs →
Google AdSense Inline Placement - Content Footer banner