B2G/Updating
This page intends to help engineers set up an environment for updating B2G devices. It focuses on low-level details of the updating tools and omits many higher-level topics. The higher-level issues are covered in XXX other doc.
Updating is the process of (i) on a build host, building incremental update packages from old version(s) to a new version; (ii) on the client, finding the right update to download; (iii) downloading the update; (iv) applying the update to existing files on the device. Each of these items are covered below.
Types of updates
B2G phones can update the entire system through FOTA updates. The technology behind FOTA updates is shared with the Android project. The locations on the phone's hard drives that can be changed using FOTA updates include the system partition, kernel, modem baseband, recovery image used for updating, or any other file on the device.
B2G can also update just the Gecko and Gaia files on device, through a mechanism we call Gecko/Gaia OTA updates. All of the Gecko and Gaia files are in the /system/b2g
directory on the device. They comprise the core Gecko runtime and the device's user interface.
FOTA updates
B2G does not depend on a particular FOTA client; the interface is abstracted through an API we call "librecovery". However, we recommend using the "GOTA" recovery client, and the discussion here assumes GOTA is being used.
FOTA update packages mainly consist of a file called update.zip
. This package consists of
- a set of binary diffs and new files required to update the client to the newer software version
- an "update script" that drives how the diffs and new files are loaded onto the client
- an internal signature used to verify the update package
Again, this format and set of files are the same as those used in normal updates of Android OSes.
B2G additionally wraps this update.zip
package in a mar
wrapper. This mar
wrapper allows an additional level of verification that's explained below.
Gecko/Gaia OTA updates
Gecko/Gaia OTA updates use the same technology that's used to update the Firefox desktop web browser. These update packages are called "MARs"
, which stands for "Mozilla ARchive". Much like the update.zip
packages discussed above, MARs
consist of a set of binary diffs and new files needed to update the client to a newer software version.
The Gecko client verifies the integrity of MARs
that it downloads, and MARs
can be signed by multiple parties.
Again, on B2G clients, Gecko/Gaia OTA updates can only change files in the /system/b2g
directory.
Why have two update technologies?
This question is not covered in detail in this document; please refer to XXX other doc. The short answer is that
- Gecko/Gaia OTA updates can be applied "in the background", while Firefox OS continues to run normally. This provides a much better user experience because users don't need to reboot their phone and wait while an update is applied. Instead, the update is applied while the user continues to use the phone, and when the update is finished the user only needs to agree to restart the main
b2g
process. This takes a matter of seconds, instead of the minutes that are usually required to apply FOTA updates. Therefore, since most updates will only need to change files in/system/b2g
, we trade off the full generality of FOTA updates for a better user experience with Gecko/Gaia OTA updates in the common case. - Gecko/Gaia OTA update packages can sometimes be smaller than FOTA update packages, though not always; they should never be larger. This means that users can sometimes have less data to download.
Building updates for multiple software versions
Since we support both OTA and FOTA updates in FirefoxOS, we have tools to help in the generation of both. At a high level, the process looks like this for each build:
- Generate a complete OTA update MAR for the contents of /system/b2g
- Generate an incremental OTA update MAR by providing the previous version's complete OTA update MAR
- Generate a complete FOTA update zip and target files zip for the device partitions
- Generate an incremental FOTA update zip by providing the previous version's target files zip
- Wrap the complete (and/or) incremental FOTA update zips in a MAR for FxOS delivery
- Deploy OTA / FOTA MAR(s) to appropriate locations for hosting
Generating a complete OTA update MAR
Use the gecko-update-full target to generate a complete update MAR for the last successful b2g build. This will place the MAR in $GECKO_OBJDIR/dist/b2g-update/b2g-gecko-update.mar:
$ ./build.sh gecko-update-full $ cp $GECKO_OBJDIR/dist/b2g-update/b2g-gecko-update.mar <dest>
Generating an incremental OTA update MAR
Pass the previous build complete OTA update MAR ($FROM_MAR) along with the current complete OTA update MAR ($TO_MAR) to build-gecko-mar.py, and it will generate an incremental MAR at $DEST_MAR:
$ ./tools/update-tools/build-gecko-mar.py --from $FROM_MAR --to $TO_MAR $DEST_MAR
Generating a complete FOTA update zip and target files zip
When performing a "standard" build, the AOSP build system will automatically generate an FOTA update.zip / target files zip, provided the kernel binary has been copied to the appropriate place under vendor. This enables boot image, recovery image, and update.zip generation.
The complete FOTA update zip lives under out/target/product/$DEVICE/$DEVICE-ota-$VARIANT.$USER.zip
The target files zip lives under out/target/product/$DEVICE/obj/PACKAGING/target_files_intermediates/$DEVICE-target_files-$VARIANT.$USER.zip
Variable values:
$DEVICE | Device name for the AOSP product |
$VARIANT | eng, user, or userdebug |
$USER | The build username |
Generating an incremental FOTA update zip
Pass the previous build FOTA target files zip ($FROM_ZIP) and the current FOTA target files zip ($TO_ZIP) to build/tools/releasetools/ota_from_target_files:
$ ./build/tools/releasetools/ota_from_target_files -v \ -i $FROM_ZIP \ -p out/host/$HOST_ARCH \ -k $FOTA_SIGNING_KEY \ $TO_ZIP \ $DEST_ZIP
Variable values:
$FROM_ZIP | The previous FOTA target files zip |
$TO_ZIP | The current FOTA target files zip |
$DEST_ZIP | The destination incremental update zip |
$HOST_ARCH | The host and arch combo (i.e. linux-x86 or darwin-x86) |
$FOTA_SIGNING_KEY | Path to the prefix for a private key and public cert for signing the update zip. $FOTA_SIGNING_ZIP.pk8 and $FOTA_SIGNING_ZIP.x509.pem should both exist on the filesystem |
Wrapping a FOTA update zip in a MAR
FxOS uses MARs to deliver all updates, whether they are complete or incremental. To wrap a FOTA update zip ($UPDATE_ZIP) in a MAR ($WRAPPED_MAR), use tools/update-tools/build-fota-mar.py:
$ ./tools/update-tools/build-fota-mar.py $UPDATE_ZIP --output=$WRAPPED_MAR
Hosting updates (respectively, polling for updates on the client side)
- interaction of server tools with build tools
- The build server uploads two files to the update server: the update.mar file and the application.ini. For GOTA updates, the build server then kicks off a local script on the update server that generates update.xml based on these files. For FOTA updates, update.xml generation is manual.
- layout of packages and manifests hosted on the server
- For GOTA updates, all .mar and application.ini files reside in a single directory that corresponds to the update channel (e.g., /data/update-channels/beta for the beta update channel); update.xml points to the newest copies of these files.
- For FOTA updates, only a single .mar, .ini, and update.xml file exist in a folder which corresponds to 'linear update' url (see below), e.g., /data/update-channels/beta/$PRODUCT/$VERSION/$BUILDID.
- (for "linear updates") how a client finds one and only one update
- When linear updates are enabled, the update url on the phone is set to http://host/%CHANNEL%/%PRODUCT_MODEL%/%VERSION%/%BUILD_ID%/update.xml. Thus, each build has a unique update url, and only one update is ever posted to that location. Thus, a phone cannot skip updates, and must apply, in sequence, every update that has been posted.
- In our testing, we have used a combination of linear updates and normal udpates; we use normal updates (which allow users to download only the most recent update) for GOTA updates, but switch to linear updates for FOTA updates, so that users cannot skip FOTA updates. Performing this switch requires that the last GOTA update before a FOTA update contain an update url change, from e.g., http://host/beta/update.xml to http://host/%CHANNEL%/%PRODUCT_MODEL%/%VERSION%/%BUILD_ID%/update.xml.
Downloading and applying updates
- poll for update manifest (update.xml)
- download signed mar
- verify, stage for being applied
- invoke
updater