1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without 7 * restriction, including without limitation the rights to use, copy, 8 * modify, merge, publish, distribute, sublicense, and/or sell copies 9 * of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 #include <efi.h> 26 #include <efilib.h> 27 28 #include <libavb_ab/libavb_ab.h> 29 30 #include "uefi_avb_boot.h" 31 #include "uefi_avb_ops.h" 32 33 EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, 34 EFI_SYSTEM_TABLE* SystemTable) { 35 AvbOps* ops; 36 AvbABFlowResult ab_result; 37 AvbSlotVerifyData* slot_data; 38 UEFIAvbBootKernelResult boot_result; 39 const char* requested_partitions[] = {"boot", NULL}; 40 bool unlocked = true; 41 char* additional_cmdline = NULL; 42 AvbSlotVerifyFlags flags; 43 44 InitializeLib(ImageHandle, SystemTable); 45 46 avb_printv("UEFI AVB-based bootloader using libavb version ", 47 avb_version_string(), 48 "\n", 49 NULL); 50 51 ops = uefi_avb_ops_new(ImageHandle); 52 if (ops == NULL) { 53 avb_fatal("Error allocating AvbOps.\n"); 54 } 55 56 if (ops->read_is_device_unlocked(ops, &unlocked) != AVB_IO_RESULT_OK) { 57 avb_fatal("Error determining whether device is unlocked.\n"); 58 } 59 avb_printv("read_is_device_unlocked() ops returned that device is ", 60 unlocked ? "UNLOCKED" : "LOCKED", 61 "\n", 62 NULL); 63 64 flags = AVB_SLOT_VERIFY_FLAGS_NONE; 65 if (unlocked) { 66 flags |= AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR; 67 } 68 69 ab_result = avb_ab_flow(ops->ab_ops, 70 requested_partitions, 71 flags, 72 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, 73 &slot_data); 74 avb_printv("avb_ab_flow() returned ", 75 avb_ab_flow_result_to_string(ab_result), 76 "\n", 77 NULL); 78 switch (ab_result) { 79 case AVB_AB_FLOW_RESULT_OK: 80 case AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR: 81 avb_printv("slot_suffix: ", slot_data->ab_suffix, "\n", NULL); 82 avb_printv("cmdline: ", slot_data->cmdline, "\n", NULL); 83 avb_printv( 84 "release string: ", 85 (const char*)((((AvbVBMetaImageHeader*)(slot_data->vbmeta_images[0] 86 .vbmeta_data))) 87 ->release_string), 88 "\n", 89 NULL); 90 /* Pass 'skip_initramfs' since we're not booting into recovery 91 * mode. Also pass the selected slot in androidboot.slot and the 92 * suffix in androidboot.slot_suffix. 93 */ 94 additional_cmdline = avb_strdupv("skip_initramfs ", 95 "androidboot.slot=", 96 slot_data->ab_suffix + 1, 97 " ", 98 "androidboot.slot_suffix=", 99 slot_data->ab_suffix, 100 NULL); 101 if (additional_cmdline == NULL) { 102 avb_fatal("Error allocating additional_cmdline.\n"); 103 } 104 boot_result = 105 uefi_avb_boot_kernel(ImageHandle, slot_data, additional_cmdline); 106 avb_fatalv("uefi_avb_boot_kernel() failed with error ", 107 uefi_avb_boot_kernel_result_to_string(boot_result), 108 "\n", 109 NULL); 110 avb_slot_verify_data_free(slot_data); 111 avb_free(additional_cmdline); 112 break; 113 case AVB_AB_FLOW_RESULT_ERROR_OOM: 114 avb_fatal("OOM error while doing A/B select flow.\n"); 115 break; 116 case AVB_AB_FLOW_RESULT_ERROR_IO: 117 avb_fatal("I/O error while doing A/B select flow.\n"); 118 break; 119 case AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS: 120 avb_fatal("No bootable slots - enter repair mode\n"); 121 break; 122 case AVB_AB_FLOW_RESULT_ERROR_INVALID_ARGUMENT: 123 avb_fatal("Invalid arguments passed\n"); 124 break; 125 } 126 uefi_avb_ops_free(ops); 127 128 return EFI_SUCCESS; 129 } 130