/* * Copyright (C) 2017 The Android Open Source Project * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include <efi.h> #include <efilib.h> #include <libavb_ab/libavb_ab.h> #include "uefi_avb_boot.h" #include "uefi_avb_ops.h" EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { AvbOps* ops; AvbABFlowResult ab_result; AvbSlotVerifyData* slot_data; UEFIAvbBootKernelResult boot_result; const char* requested_partitions[] = {"boot", NULL}; bool unlocked = true; char* additional_cmdline = NULL; AvbSlotVerifyFlags flags; InitializeLib(ImageHandle, SystemTable); avb_printv("UEFI AVB-based bootloader using libavb version ", avb_version_string(), "\n", NULL); ops = uefi_avb_ops_new(ImageHandle); if (ops == NULL) { avb_fatal("Error allocating AvbOps.\n"); } if (ops->read_is_device_unlocked(ops, &unlocked) != AVB_IO_RESULT_OK) { avb_fatal("Error determining whether device is unlocked.\n"); } avb_printv("read_is_device_unlocked() ops returned that device is ", unlocked ? "UNLOCKED" : "LOCKED", "\n", NULL); flags = AVB_SLOT_VERIFY_FLAGS_NONE; if (unlocked) { flags |= AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR; } ab_result = avb_ab_flow(ops->ab_ops, requested_partitions, flags, AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, &slot_data); avb_printv("avb_ab_flow() returned ", avb_ab_flow_result_to_string(ab_result), "\n", NULL); switch (ab_result) { case AVB_AB_FLOW_RESULT_OK: case AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR: avb_printv("slot_suffix: ", slot_data->ab_suffix, "\n", NULL); avb_printv("cmdline: ", slot_data->cmdline, "\n", NULL); avb_printv( "release string: ", (const char*)((((AvbVBMetaImageHeader*)(slot_data->vbmeta_images[0] .vbmeta_data))) ->release_string), "\n", NULL); /* Pass 'skip_initramfs' since we're not booting into recovery * mode. Also pass the selected slot in androidboot.slot and the * suffix in androidboot.slot_suffix. */ additional_cmdline = avb_strdupv("skip_initramfs ", "androidboot.slot=", slot_data->ab_suffix + 1, " ", "androidboot.slot_suffix=", slot_data->ab_suffix, NULL); if (additional_cmdline == NULL) { avb_fatal("Error allocating additional_cmdline.\n"); } boot_result = uefi_avb_boot_kernel(ImageHandle, slot_data, additional_cmdline); avb_fatalv("uefi_avb_boot_kernel() failed with error ", uefi_avb_boot_kernel_result_to_string(boot_result), "\n", NULL); avb_slot_verify_data_free(slot_data); avb_free(additional_cmdline); break; case AVB_AB_FLOW_RESULT_ERROR_OOM: avb_fatal("OOM error while doing A/B select flow.\n"); break; case AVB_AB_FLOW_RESULT_ERROR_IO: avb_fatal("I/O error while doing A/B select flow.\n"); break; case AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS: avb_fatal("No bootable slots - enter repair mode\n"); break; case AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT: avb_fatal("Invalid arguments passed\n"); break; } uefi_avb_ops_free(ops); return EFI_SUCCESS; }