David Zeuthen | d9c76c7 | 2017-01-11 15:42:04 -0500 | [diff] [blame] | 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; |
David Zeuthen | 19c3843 | 2017-02-16 13:08:38 -0500 | [diff] [blame] | 41 | char* additional_cmdline = NULL; |
David Zeuthen | d9c76c7 | 2017-01-11 15:42:04 -0500 | [diff] [blame] | 42 | |
| 43 | InitializeLib(ImageHandle, SystemTable); |
| 44 | |
David Zeuthen | e3cadca | 2017-02-22 21:25:46 -0500 | [diff] [blame] | 45 | avb_printv("UEFI AVB-based bootloader using libavb version ", |
| 46 | avb_version_string(), |
| 47 | "\n", |
| 48 | NULL); |
David Zeuthen | d9c76c7 | 2017-01-11 15:42:04 -0500 | [diff] [blame] | 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: |
David Zeuthen | e3cadca | 2017-02-22 21:25:46 -0500 | [diff] [blame] | 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); |
David Zeuthen | 19c3843 | 2017-02-16 13:08:38 -0500 | [diff] [blame] | 83 | /* Pass 'skip_initramfs' since we're not booting into recovery |
David Zeuthen | b60834f | 2017-04-13 11:56:21 -0400 | [diff] [blame^] | 84 | * mode. Also pass the selected slot in androidboot.slot and the |
| 85 | * suffix in androidboot.slot_suffix. |
David Zeuthen | 19c3843 | 2017-02-16 13:08:38 -0500 | [diff] [blame] | 86 | */ |
| 87 | additional_cmdline = avb_strdupv("skip_initramfs ", |
David Zeuthen | b60834f | 2017-04-13 11:56:21 -0400 | [diff] [blame^] | 88 | "androidboot.slot=", |
| 89 | slot_data->ab_suffix + 1, |
| 90 | " ", |
David Zeuthen | 19c3843 | 2017-02-16 13:08:38 -0500 | [diff] [blame] | 91 | "androidboot.slot_suffix=", |
| 92 | slot_data->ab_suffix, |
| 93 | NULL); |
| 94 | if (additional_cmdline == NULL) { |
| 95 | avb_fatal("Error allocating additional_cmdline.\n"); |
| 96 | } |
David Zeuthen | d9c76c7 | 2017-01-11 15:42:04 -0500 | [diff] [blame] | 97 | boot_result = |
David Zeuthen | 19c3843 | 2017-02-16 13:08:38 -0500 | [diff] [blame] | 98 | uefi_avb_boot_kernel(ImageHandle, slot_data, additional_cmdline); |
David Zeuthen | d9c76c7 | 2017-01-11 15:42:04 -0500 | [diff] [blame] | 99 | avb_fatalv("uefi_avb_boot_kernel() failed with error ", |
| 100 | uefi_avb_boot_kernel_result_to_string(boot_result), |
| 101 | "\n", |
| 102 | NULL); |
| 103 | avb_slot_verify_data_free(slot_data); |
David Zeuthen | 19c3843 | 2017-02-16 13:08:38 -0500 | [diff] [blame] | 104 | avb_free(additional_cmdline); |
David Zeuthen | d9c76c7 | 2017-01-11 15:42:04 -0500 | [diff] [blame] | 105 | break; |
| 106 | case AVB_AB_FLOW_RESULT_ERROR_OOM: |
| 107 | avb_fatal("OOM error while doing A/B select flow.\n"); |
| 108 | break; |
| 109 | case AVB_AB_FLOW_RESULT_ERROR_IO: |
| 110 | avb_fatal("I/O error while doing A/B select flow.\n"); |
| 111 | break; |
| 112 | case AVB_AB_FLOW_RESULT_ERROR_NO_BOOTABLE_SLOTS: |
| 113 | avb_fatal("No bootable slots - enter repair mode\n"); |
| 114 | break; |
| 115 | } |
| 116 | uefi_avb_ops_free(ops); |
| 117 | |
| 118 | return EFI_SUCCESS; |
| 119 | } |