Modifications to Amazon script to compile a custom bootloader for the FireTV 2nd gen Cube, with U-Boot & Fastboot restrictions removed.
This bootloader compiler is a modification of the build script included with FireTVCubeGen2-7.2.0.4-20191004.tar.bz2 from Amazon's FireTV source code page.
Running the compilation script requires installing aarch64-none-elf & arm-none-eabi compiler Toolchains. Follow Odroid's Toolchain installation guide. Add the installed compiler paths to build_uboot_config.sh
, and run build_uboot_config.sh
to update the script paths.
To compile the bootloader run:
sudo ./build_uboot.sh platform.tar output_directory_name
Platform.tar is the compressed bootloader & kernel source from FireTVCubeGen2-7.2.0.4-20191004.tar.bz2. Merge the modified files provided here into your platform.tar to remove fastboot & U-Boot command restrictions from your build.
output_directory_name is the completed bootloader image destination.
The component images that make up the bootloader, including bl33.bin.enc
can be found in:
tmp/tmp.randomstring/src/bootable/bootloader/uboot-amlogic/s922x/fip/_tmp/
To insert the modified U-boot image (bl33.bin.enc
) into the signed bootloader image obtained from the Amazon FireTV OTA update, overwriting the orginal U-Boot code.
- Decrypt the Bl33 portion of the signed bootloader with the AES key found at 0x00010EEC (within Bl30) of the signed bootloader. Note: this will require already having extracted the AES key located in the bootrom needed to decrypt Bl2 & Bl30
sudo openssl enc -aes-256-cbc -nopad -d -K 0000000000000000000000000000000000000000000000000000000000000000 -iv 00000000000000000000000000000000 -in u-boot.bin.signed -out bootloader.img
- The patched Bl33 image (
bl33.bin.enc
) and unmodified Bl33 within the decrypted bootloader (bootloader.img
) are now aligned using the LZ4C magic to identify the beginning of the compression scheme used on U-Boot.
IN_OFFSET=`grep --byte-offset --only-matching --text LZ4C bl33.bin.enc | head -1 | cut -d: -f1`
OUT_OFFSET=`grep --byte-offset --only-matching --text LZ4C bootloader.img | head -1 | cut -d: -f1`
Bl33.bin.enc
is merged into bootloader.img, and the old Bl33 is overwritten
sudo dd if=bl33.bin.enc of=bootloader.img skip=$IN_OFFSET seek=$OUT_OFFSET bs=1 conv=notrunc
- Lastly, we re-encrypt the the end of
bootloader.img
using the same AES key from step 1).
sudo openssl enc -aes-256-cbc -nopad -e -K 0000000000000000000000000000000000000000000000000000000000000000 -iv 00000000000000000000000000000000 -in bootloader.img -out bootloader.img.enc
Minor modifications were made to the build script to disable the automatic cleanup following compilation completion. Deletion of the working folder is disabled to to make all the components of the bootloader accessible including bl33.bin.enc
(patched U-Boot image).
[build_uboot.sh]
Disable deletion of the working folder
commented out line 48
#trap "rm -rf $WORKSPACE_DIR" EXIT
[mk_script.sh]
Disable deletion of the bootloader component images
commented out lines 140-144
function clean() {
echo "Clean up"
# cd ${UBOOT_SRC_FOLDER}
# make distclean
# cd ${MAIN_FOLDER}
# rm ${FIP_BUILD_FOLDER} -rf
# rm ${BUILD_FOLDER}/* -rf
return
}
[amzn_lockdown.c] Original
Removing Amazon's U-Boot commandline restrictions
bool amzn_is_command_blocked(const char *cmd)
{
int i = 0, found = 0;
/* Are we in lock down? */
if (lockdown_commands == false)
return false;
/* Is this an engineering device? */
if (amzn_target_device_type() == AMZN_ENGINEERING_DEVICE)
return false;
/* Are we un-locked? */
if (amzn_target_is_unlocked())
return false;
if (amzn_target_is_onetime_unlocked())
return false;
/* If command is on the white-list, allow */
for (i = 0; i < ARRAY_SIZE(whitelisted_commands); i++)
if (strcmp(whitelisted_commands[i], cmd) == 0)
found = 1;
/* Not on the white-list? Block */
if (!found)
return true;
return false;
}
[amzn_lockdown.c] Modified
Edited down function and moved up to line 22
bool amzn_is_command_blocked(const char *cmd)
{
return false;
}
===========================================
[amzn_fastboot_lockdown.c] Original
Removing Amazon's Fastboot command restrictions
__attribute__((weak)) int is_locked_production_device() {
#if defined(UFBL_FEATURE_SECURE_BOOT)
return (AMZN_PRODUCTION_DEVICE == amzn_target_device_type()) && (1 != g_boot_arg->unlocked);
#else
return 0;
#endif
}
#else /* UFBL_PROJ_ABC */
__attribute__((weak)) int is_locked_production_device() {
#if defined(UFBL_FEATURE_SECURE_BOOT) && defined(UFBL_FEATURE_UNLOCK)
return (AMZN_PRODUCTION_DEVICE == amzn_target_device_type()
&& (!amzn_target_is_unlocked())
#if defined(UFBL_FEATURE_TEMP_UNLOCK)
&& (!amzn_target_is_temp_unlocked())
#endif
#if defined(UFBL_FEATURE_ONETIME_UNLOCK)
&& (!amzn_target_is_onetime_unlocked())
#endif
);
#else
return 0;
#endif
}
#endif /* UFBL_PROJ_ABC */
[amzn_fastboot_lockdown.c] 1st Patch
__attribute__((weak)) int is_locked_production_device() {
return 0;
}
[amzn_fastboot_lockdown.c] Original
for (i = 0; i < sizeof(blacklist) / sizeof(blacklist[0]); ++i) {
if (memcmp(buffer, blacklist[i], strlen(blacklist[i])) == 0) {
return 1;
}
}
amzn_extends_fastboot_blacklist(&list, &length);
if (list != NULL && length > 0) {
for (i = 0; i < length; ++i) {
if (memcmp(buffer, list[i], strlen(list[i])) == 0) {
return 1;
}
}
}
return 0;
}
[amzn_fastboot_lockdown.c] 2nd Patch
for (i = 0; i < sizeof(blacklist) / sizeof(blacklist[0]); ++i) {
if (memcmp(buffer, blacklist[i], strlen(blacklist[i])) == 0) {
return 0;
}
}
amzn_extends_fastboot_blacklist(&list, &length);
if (list != NULL && length > 0) {
for (i = 0; i < length; ++i) {
if (memcmp(buffer, list[i], strlen(list[i])) == 0) {
return 0;
}
}
}
return 0;
}
===========================================
[image_verify.c] Original
Remove the fastboot flash image verification check
int
amzn_image_verify(const void *image,
unsigned char *signature,
unsigned int image_size, meta_data_handler handler)
{
int auth = 0;
char *digest = NULL;
if (!(digest = amzn_plat_alloc(SHA256_DIGEST_LENGTH))) {
dprintf(CRITICAL, "ERROR: Unable to allocate image hash\n");
goto cleanup;
}
memset(digest, 0, SHA256_DIGEST_LENGTH);
/*
* Calculate hash of image for comparison
*/
amzn_target_sha256(image, image_size, digest);
if (amzn_verify_image(AMZN_PRODUCTION_CERT, digest,
signature, handler)) {
if (amzn_target_device_type() == AMZN_PRODUCTION_DEVICE) {
dprintf(ALWAYS,
"Image FAILED AUTHENTICATION on PRODUCTION device\n");
/* Failed verification */
goto cleanup;
} else {
dprintf(ALWAYS,
"Authentication failed on engineering device with production certificate\n");
}
if (amzn_target_device_type() != AMZN_ENGINEERING_DEVICE) {
dprintf(ALWAYS,
"%s: Unknown device type!\n", UFBL_STR(__FUNCTION__));
goto cleanup;
}
/* Engineering device */
if (amzn_verify_image(AMZN_ENGINEERING_CERT, digest,
signature, handler)) {
dprintf(ALWAYS,
"Image FAILED AUTHENTICATION on ENGINEERING device\n");
goto cleanup;
}
} else {
dprintf(ALWAYS,
"Image AUTHENTICATED with PRODUCTION certificate\n");
}
auth = 1;
cleanup:
if (digest)
amzn_plat_free(digest);
return auth;
}
[image_verify.c] Patched
int
amzn_image_verify(const void *image,
unsigned char *signature,
unsigned int image_size, meta_data_handler handler)
{
return 1;
}
===========================================
[secure_boot.c] Original
Designate the Cube as an engineering device. This is a redundancy that should cover any restrictions that may have been missed.
int amzn_target_device_type(void)
{
/* Is anti-rollback enabled? */
if (query_efuse_status("ARB") == 1)
return AMZN_PRODUCTION_DEVICE;
else
return AMZN_ENGINEERING_DEVICE;
}
[secure_boot.c] Patched
int amzn_target_device_type(void)
{
/* Is anti-rollback enabled? */
if (query_efuse_status("ARB") == 1)
return AMZN_ENGINEERING_DEVICE;
else
return AMZN_ENGINEERING_DEVICE;
}
The bootmode is set in
[main.c]
To automatically boot to fastboot add the following two lines above autoboot_command(s); (lines 144-145):
#endif //#if defined(CONFIG_AML_UBOOT_AUTO_TEST)
run_command("fastboot", 0);
run_preboot_environment_command();
autoboot_command(s);
To boot to Amlogic's burn mode:
#endif //#if defined(CONFIG_AML_UBOOT_AUTO_TEST)
run_command("update", 0);
run_preboot_environment_command();
autoboot_command(s);
To automatically drop into the U-Boot console, simply comment out autoboot_command(s);
#endif //#if defined(CONFIG_AML_UBOOT_AUTO_TEST)
// autoboot_command(s);