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 43 InitializeLib(ImageHandle, SystemTable); 44 45 avb_printv("UEFI AVB-based bootloader using libavb version ", 46 avb_version_string(), 47 "\n", 48 NULL); 49 50 ops = uefi_avb_ops_new(ImageHandle); 51 if (ops == NULL) { 52 avb_fatal("Error allocating AvbOps.\n"); 53 } 54 55 if (ops->read_is_device_unlocked(ops, &unlocked) != AVB_IO_RESULT_OK) { 56 avb_fatal("Error determining whether device is unlocked.\n"); 57 } 58 avb_printv("read_is_device_unlocked() ops returned that device is ", 59 unlocked ? "UNLOCKED" : "LOCKED", 60 "\n", 61 NULL); 62 63 ab_result = avb_ab_flow(ops->ab_ops, 64 requested_partitions, 65 unlocked /* allow_verification_error */, 66 &slot_data); 67 avb_printv("avb_ab_flow() returned ", 68 avb_ab_flow_result_to_string(ab_result), 69 "\n", 70 NULL); 71 switch (ab_result) { 72 case AVB_AB_FLOW_RESULT_OK: 73 case AVB_AB_FLOW_RESULT_OK_WITH_VERIFICATION_ERROR: 74 avb_printv("slot_suffix: ", slot_data->ab_suffix, "\n", NULL); 75 avb_printv("cmdline: ", slot_data->cmdline, "\n", NULL); 76 avb_printv( 77 "release string: ", 78 (const char*)((((AvbVBMetaImageHeader*)(slot_data->vbmeta_images[0] 79 .vbmeta_data))) 80 ->release_string), 81 "\n", 82 NULL); 83 /* Pass 'skip_initramfs' since we're not booting into recovery 84 * mode. Also pass the selected slot in androidboot.slot_suffix. 85 */ 86 additional_cmdline = avb_strdupv("skip_initramfs ", 87 "androidboot.slot_suffix=", 88 slot_data->ab_suffix, 89 NULL); 90 if (additional_cmdline == NULL) { 91 avb_fatal("Error allocating additional_cmdline.\n"); 92 } 93 boot_result = 94 uefi_avb_boot_kernel(ImageHandle, slot_data, additional_cmdline); 95 avb_fatalv("uefi_avb_boot_kernel() failed with error ", 96 uefi_avb_boot_kernel_result_to_string(boot_result), 97 "\n", 98 NULL); 99 avb_slot_verify_data_free(slot_data); 100 avb_free(additional_cmdline); 101 break; 102 case AVB_AB_FLOW_RESULT_ERROR_OOM: 103 avb_fatal("OOM error while doing A/B select flow.\n"); 104 break; 105 case AVB_AB_FLOW_RESULT_ERROR_IO: 106 avb_fatal("I/O error while doing A/B select flow.\n"); 107 break; 108 case AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS: 109 avb_fatal("No bootable slots - enter repair mode\n"); 110 break; 111 } 112 uefi_avb_ops_free(ops); 113 114 return EFI_SUCCESS; 115 } 116