xref: /aosp_15_r20/external/avb/examples/uefi/uefi_avb_boot.c (revision d289c2ba6de359471b23d594623b906876bc48a0)
1*d289c2baSAndroid Build Coastguard Worker /*
2*d289c2baSAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*d289c2baSAndroid Build Coastguard Worker  *
4*d289c2baSAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person
5*d289c2baSAndroid Build Coastguard Worker  * obtaining a copy of this software and associated documentation
6*d289c2baSAndroid Build Coastguard Worker  * files (the "Software"), to deal in the Software without
7*d289c2baSAndroid Build Coastguard Worker  * restriction, including without limitation the rights to use, copy,
8*d289c2baSAndroid Build Coastguard Worker  * modify, merge, publish, distribute, sublicense, and/or sell copies
9*d289c2baSAndroid Build Coastguard Worker  * of the Software, and to permit persons to whom the Software is
10*d289c2baSAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
11*d289c2baSAndroid Build Coastguard Worker  *
12*d289c2baSAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be
13*d289c2baSAndroid Build Coastguard Worker  * included in all copies or substantial portions of the Software.
14*d289c2baSAndroid Build Coastguard Worker  *
15*d289c2baSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*d289c2baSAndroid Build Coastguard Worker  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*d289c2baSAndroid Build Coastguard Worker  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18*d289c2baSAndroid Build Coastguard Worker  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19*d289c2baSAndroid Build Coastguard Worker  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20*d289c2baSAndroid Build Coastguard Worker  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21*d289c2baSAndroid Build Coastguard Worker  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*d289c2baSAndroid Build Coastguard Worker  * SOFTWARE.
23*d289c2baSAndroid Build Coastguard Worker  */
24*d289c2baSAndroid Build Coastguard Worker 
25*d289c2baSAndroid Build Coastguard Worker #include <efi.h>
26*d289c2baSAndroid Build Coastguard Worker #include <efilib.h>
27*d289c2baSAndroid Build Coastguard Worker 
28*d289c2baSAndroid Build Coastguard Worker #include "bootimg.h"
29*d289c2baSAndroid Build Coastguard Worker 
30*d289c2baSAndroid Build Coastguard Worker #include "uefi_avb_boot.h"
31*d289c2baSAndroid Build Coastguard Worker #include "uefi_avb_util.h"
32*d289c2baSAndroid Build Coastguard Worker 
33*d289c2baSAndroid Build Coastguard Worker /* See Documentation/x86/boot.txt for this struct and more information
34*d289c2baSAndroid Build Coastguard Worker  * about the boot/handover protocol.
35*d289c2baSAndroid Build Coastguard Worker  */
36*d289c2baSAndroid Build Coastguard Worker 
37*d289c2baSAndroid Build Coastguard Worker #define SETUP_MAGIC 0x53726448 /* "HdrS" */
38*d289c2baSAndroid Build Coastguard Worker 
39*d289c2baSAndroid Build Coastguard Worker struct SetupHeader {
40*d289c2baSAndroid Build Coastguard Worker   UINT8 boot_sector[0x01f1];
41*d289c2baSAndroid Build Coastguard Worker   UINT8 setup_secs;
42*d289c2baSAndroid Build Coastguard Worker   UINT16 root_flags;
43*d289c2baSAndroid Build Coastguard Worker   UINT32 sys_size;
44*d289c2baSAndroid Build Coastguard Worker   UINT16 ram_size;
45*d289c2baSAndroid Build Coastguard Worker   UINT16 video_mode;
46*d289c2baSAndroid Build Coastguard Worker   UINT16 root_dev;
47*d289c2baSAndroid Build Coastguard Worker   UINT16 signature;
48*d289c2baSAndroid Build Coastguard Worker   UINT16 jump;
49*d289c2baSAndroid Build Coastguard Worker   UINT32 header;
50*d289c2baSAndroid Build Coastguard Worker   UINT16 version;
51*d289c2baSAndroid Build Coastguard Worker   UINT16 su_switch;
52*d289c2baSAndroid Build Coastguard Worker   UINT16 setup_seg;
53*d289c2baSAndroid Build Coastguard Worker   UINT16 start_sys;
54*d289c2baSAndroid Build Coastguard Worker   UINT16 kernel_ver;
55*d289c2baSAndroid Build Coastguard Worker   UINT8 loader_id;
56*d289c2baSAndroid Build Coastguard Worker   UINT8 load_flags;
57*d289c2baSAndroid Build Coastguard Worker   UINT16 movesize;
58*d289c2baSAndroid Build Coastguard Worker   UINT32 code32_start;
59*d289c2baSAndroid Build Coastguard Worker   UINT32 ramdisk_start;
60*d289c2baSAndroid Build Coastguard Worker   UINT32 ramdisk_len;
61*d289c2baSAndroid Build Coastguard Worker   UINT32 bootsect_kludge;
62*d289c2baSAndroid Build Coastguard Worker   UINT16 heap_end;
63*d289c2baSAndroid Build Coastguard Worker   UINT8 ext_loader_ver;
64*d289c2baSAndroid Build Coastguard Worker   UINT8 ext_loader_type;
65*d289c2baSAndroid Build Coastguard Worker   UINT32 cmd_line_ptr;
66*d289c2baSAndroid Build Coastguard Worker   UINT32 ramdisk_max;
67*d289c2baSAndroid Build Coastguard Worker   UINT32 kernel_alignment;
68*d289c2baSAndroid Build Coastguard Worker   UINT8 relocatable_kernel;
69*d289c2baSAndroid Build Coastguard Worker   UINT8 min_alignment;
70*d289c2baSAndroid Build Coastguard Worker   UINT16 xloadflags;
71*d289c2baSAndroid Build Coastguard Worker   UINT32 cmdline_size;
72*d289c2baSAndroid Build Coastguard Worker   UINT32 hardware_subarch;
73*d289c2baSAndroid Build Coastguard Worker   UINT64 hardware_subarch_data;
74*d289c2baSAndroid Build Coastguard Worker   UINT32 payload_offset;
75*d289c2baSAndroid Build Coastguard Worker   UINT32 payload_length;
76*d289c2baSAndroid Build Coastguard Worker   UINT64 setup_data;
77*d289c2baSAndroid Build Coastguard Worker   UINT64 pref_address;
78*d289c2baSAndroid Build Coastguard Worker   UINT32 init_size;
79*d289c2baSAndroid Build Coastguard Worker   UINT32 handover_offset;
80*d289c2baSAndroid Build Coastguard Worker } __attribute__((packed));
81*d289c2baSAndroid Build Coastguard Worker 
82*d289c2baSAndroid Build Coastguard Worker #ifdef __x86_64__
83*d289c2baSAndroid Build Coastguard Worker typedef VOID (*handover_f)(VOID* image,
84*d289c2baSAndroid Build Coastguard Worker                            EFI_SYSTEM_TABLE* table,
85*d289c2baSAndroid Build Coastguard Worker                            struct SetupHeader* setup);
linux_efi_handover(EFI_HANDLE image,struct SetupHeader * setup)86*d289c2baSAndroid Build Coastguard Worker static inline VOID linux_efi_handover(EFI_HANDLE image,
87*d289c2baSAndroid Build Coastguard Worker                                       struct SetupHeader* setup) {
88*d289c2baSAndroid Build Coastguard Worker   handover_f handover;
89*d289c2baSAndroid Build Coastguard Worker 
90*d289c2baSAndroid Build Coastguard Worker   asm volatile("cli");
91*d289c2baSAndroid Build Coastguard Worker   handover =
92*d289c2baSAndroid Build Coastguard Worker       (handover_f)((UINTN)setup->code32_start + 512 + setup->handover_offset);
93*d289c2baSAndroid Build Coastguard Worker   handover(image, ST, setup);
94*d289c2baSAndroid Build Coastguard Worker }
95*d289c2baSAndroid Build Coastguard Worker #else
96*d289c2baSAndroid Build Coastguard Worker typedef VOID (*handover_f)(VOID* image,
97*d289c2baSAndroid Build Coastguard Worker                            EFI_SYSTEM_TABLE* table,
98*d289c2baSAndroid Build Coastguard Worker                            struct SetupHeader* setup)
99*d289c2baSAndroid Build Coastguard Worker     __attribute__((regparm(0)));
linux_efi_handover(EFI_HANDLE image,struct SetupHeader * setup)100*d289c2baSAndroid Build Coastguard Worker static inline VOID linux_efi_handover(EFI_HANDLE image,
101*d289c2baSAndroid Build Coastguard Worker                                       struct SetupHeader* setup) {
102*d289c2baSAndroid Build Coastguard Worker   handover_f handover;
103*d289c2baSAndroid Build Coastguard Worker 
104*d289c2baSAndroid Build Coastguard Worker   handover = (handover_f)((UINTN)setup->code32_start + setup->handover_offset);
105*d289c2baSAndroid Build Coastguard Worker   handover(image, ST, setup);
106*d289c2baSAndroid Build Coastguard Worker }
107*d289c2baSAndroid Build Coastguard Worker #endif
108*d289c2baSAndroid Build Coastguard Worker 
round_up(size_t value,size_t size)109*d289c2baSAndroid Build Coastguard Worker static size_t round_up(size_t value, size_t size) {
110*d289c2baSAndroid Build Coastguard Worker   size_t ret = value + size - 1;
111*d289c2baSAndroid Build Coastguard Worker   ret /= size;
112*d289c2baSAndroid Build Coastguard Worker   ret *= size;
113*d289c2baSAndroid Build Coastguard Worker   return ret;
114*d289c2baSAndroid Build Coastguard Worker }
115*d289c2baSAndroid Build Coastguard Worker 
uefi_avb_boot_kernel(EFI_HANDLE efi_image_handle,AvbSlotVerifyData * slot_data,const char * cmdline_extra)116*d289c2baSAndroid Build Coastguard Worker UEFIAvbBootKernelResult uefi_avb_boot_kernel(EFI_HANDLE efi_image_handle,
117*d289c2baSAndroid Build Coastguard Worker                                              AvbSlotVerifyData* slot_data,
118*d289c2baSAndroid Build Coastguard Worker                                              const char* cmdline_extra) {
119*d289c2baSAndroid Build Coastguard Worker   UEFIAvbBootKernelResult ret;
120*d289c2baSAndroid Build Coastguard Worker   const boot_img_hdr* header;
121*d289c2baSAndroid Build Coastguard Worker   EFI_STATUS err;
122*d289c2baSAndroid Build Coastguard Worker   UINT8* kernel_buf = NULL;
123*d289c2baSAndroid Build Coastguard Worker   UINT8* initramfs_buf = NULL;
124*d289c2baSAndroid Build Coastguard Worker   UINT8* cmdline_utf8 = NULL;
125*d289c2baSAndroid Build Coastguard Worker   AvbPartitionData* boot;
126*d289c2baSAndroid Build Coastguard Worker   size_t offset;
127*d289c2baSAndroid Build Coastguard Worker   uint64_t total_size;
128*d289c2baSAndroid Build Coastguard Worker   size_t initramfs_size;
129*d289c2baSAndroid Build Coastguard Worker   size_t cmdline_first_len;
130*d289c2baSAndroid Build Coastguard Worker   size_t cmdline_second_len;
131*d289c2baSAndroid Build Coastguard Worker   size_t cmdline_extra_len;
132*d289c2baSAndroid Build Coastguard Worker   size_t cmdline_utf8_len;
133*d289c2baSAndroid Build Coastguard Worker   struct SetupHeader* image_setup;
134*d289c2baSAndroid Build Coastguard Worker   struct SetupHeader* setup;
135*d289c2baSAndroid Build Coastguard Worker   EFI_PHYSICAL_ADDRESS addr;
136*d289c2baSAndroid Build Coastguard Worker 
137*d289c2baSAndroid Build Coastguard Worker   if (slot_data->num_loaded_partitions != 1) {
138*d289c2baSAndroid Build Coastguard Worker     avb_error("No boot partition.\n");
139*d289c2baSAndroid Build Coastguard Worker     ret = UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_PARTITION_INVALID_FORMAT;
140*d289c2baSAndroid Build Coastguard Worker     goto out;
141*d289c2baSAndroid Build Coastguard Worker   }
142*d289c2baSAndroid Build Coastguard Worker 
143*d289c2baSAndroid Build Coastguard Worker   boot = &slot_data->loaded_partitions[0];
144*d289c2baSAndroid Build Coastguard Worker   if (avb_strcmp(boot->partition_name, "boot") != 0) {
145*d289c2baSAndroid Build Coastguard Worker     avb_error("Unexpected partition name '", boot->partition_name, "'.\n");
146*d289c2baSAndroid Build Coastguard Worker     ret = UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_PARTITION_INVALID_FORMAT;
147*d289c2baSAndroid Build Coastguard Worker     goto out;
148*d289c2baSAndroid Build Coastguard Worker   }
149*d289c2baSAndroid Build Coastguard Worker 
150*d289c2baSAndroid Build Coastguard Worker   header = (const boot_img_hdr*)boot->data;
151*d289c2baSAndroid Build Coastguard Worker 
152*d289c2baSAndroid Build Coastguard Worker   /* Check boot image header magic field. */
153*d289c2baSAndroid Build Coastguard Worker   if (avb_memcmp(BOOT_MAGIC, header->magic, BOOT_MAGIC_SIZE)) {
154*d289c2baSAndroid Build Coastguard Worker     avb_error("Wrong boot image header magic.\n");
155*d289c2baSAndroid Build Coastguard Worker     ret = UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_PARTITION_INVALID_FORMAT;
156*d289c2baSAndroid Build Coastguard Worker     goto out;
157*d289c2baSAndroid Build Coastguard Worker   }
158*d289c2baSAndroid Build Coastguard Worker 
159*d289c2baSAndroid Build Coastguard Worker   /* Sanity check header. */
160*d289c2baSAndroid Build Coastguard Worker   total_size = header->kernel_size;
161*d289c2baSAndroid Build Coastguard Worker   if (!avb_safe_add_to(&total_size, header->ramdisk_size) ||
162*d289c2baSAndroid Build Coastguard Worker       !avb_safe_add_to(&total_size, header->second_size)) {
163*d289c2baSAndroid Build Coastguard Worker     avb_error("Overflow while adding sizes of kernel and initramfs.\n");
164*d289c2baSAndroid Build Coastguard Worker     ret = UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_PARTITION_INVALID_FORMAT;
165*d289c2baSAndroid Build Coastguard Worker     goto out;
166*d289c2baSAndroid Build Coastguard Worker   }
167*d289c2baSAndroid Build Coastguard Worker   if (total_size > boot->data_size) {
168*d289c2baSAndroid Build Coastguard Worker     avb_error("Invalid kernel/initramfs sizes.\n");
169*d289c2baSAndroid Build Coastguard Worker     ret = UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_PARTITION_INVALID_FORMAT;
170*d289c2baSAndroid Build Coastguard Worker     goto out;
171*d289c2baSAndroid Build Coastguard Worker   }
172*d289c2baSAndroid Build Coastguard Worker 
173*d289c2baSAndroid Build Coastguard Worker   /* The kernel has to be in its own specific memory pool. */
174*d289c2baSAndroid Build Coastguard Worker   err = uefi_call_wrapper(BS->AllocatePool,
175*d289c2baSAndroid Build Coastguard Worker                           NUM_ARGS_ALLOCATE_POOL,
176*d289c2baSAndroid Build Coastguard Worker                           EfiLoaderCode,
177*d289c2baSAndroid Build Coastguard Worker                           header->kernel_size,
178*d289c2baSAndroid Build Coastguard Worker                           &kernel_buf);
179*d289c2baSAndroid Build Coastguard Worker   if (EFI_ERROR(err)) {
180*d289c2baSAndroid Build Coastguard Worker     avb_error("Could not allocate kernel buffer.\n");
181*d289c2baSAndroid Build Coastguard Worker     ret = UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_OOM;
182*d289c2baSAndroid Build Coastguard Worker     goto out;
183*d289c2baSAndroid Build Coastguard Worker   }
184*d289c2baSAndroid Build Coastguard Worker   avb_memcpy(kernel_buf, boot->data + header->page_size, header->kernel_size);
185*d289c2baSAndroid Build Coastguard Worker 
186*d289c2baSAndroid Build Coastguard Worker   /* Ditto for the initrd. */
187*d289c2baSAndroid Build Coastguard Worker   initramfs_buf = NULL;
188*d289c2baSAndroid Build Coastguard Worker   initramfs_size = header->ramdisk_size + header->second_size;
189*d289c2baSAndroid Build Coastguard Worker   if (initramfs_size > 0) {
190*d289c2baSAndroid Build Coastguard Worker     err = uefi_call_wrapper(BS->AllocatePool,
191*d289c2baSAndroid Build Coastguard Worker                             NUM_ARGS_ALLOCATE_POOL,
192*d289c2baSAndroid Build Coastguard Worker                             EfiLoaderCode,
193*d289c2baSAndroid Build Coastguard Worker                             initramfs_size,
194*d289c2baSAndroid Build Coastguard Worker                             &initramfs_buf);
195*d289c2baSAndroid Build Coastguard Worker     if (EFI_ERROR(err)) {
196*d289c2baSAndroid Build Coastguard Worker       avb_error("Could not allocate initrd buffer.\n");
197*d289c2baSAndroid Build Coastguard Worker       ret = UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_OOM;
198*d289c2baSAndroid Build Coastguard Worker       goto out;
199*d289c2baSAndroid Build Coastguard Worker     }
200*d289c2baSAndroid Build Coastguard Worker     /* Concatente the first and second initramfs. */
201*d289c2baSAndroid Build Coastguard Worker     offset = header->page_size;
202*d289c2baSAndroid Build Coastguard Worker     offset += round_up(header->kernel_size, header->page_size);
203*d289c2baSAndroid Build Coastguard Worker     avb_memcpy(initramfs_buf, boot->data + offset, header->ramdisk_size);
204*d289c2baSAndroid Build Coastguard Worker     offset += round_up(header->ramdisk_size, header->page_size);
205*d289c2baSAndroid Build Coastguard Worker     avb_memcpy(initramfs_buf, boot->data + offset, header->second_size);
206*d289c2baSAndroid Build Coastguard Worker   }
207*d289c2baSAndroid Build Coastguard Worker 
208*d289c2baSAndroid Build Coastguard Worker   /* Prepare the command-line. */
209*d289c2baSAndroid Build Coastguard Worker   cmdline_first_len = avb_strlen((const char*)header->cmdline);
210*d289c2baSAndroid Build Coastguard Worker   cmdline_second_len = avb_strlen(slot_data->cmdline);
211*d289c2baSAndroid Build Coastguard Worker   cmdline_extra_len = cmdline_extra != NULL ? avb_strlen(cmdline_extra) : 0;
212*d289c2baSAndroid Build Coastguard Worker   if (cmdline_extra_len > 0) {
213*d289c2baSAndroid Build Coastguard Worker     cmdline_extra_len += 1;
214*d289c2baSAndroid Build Coastguard Worker   }
215*d289c2baSAndroid Build Coastguard Worker   cmdline_utf8_len =
216*d289c2baSAndroid Build Coastguard Worker       cmdline_first_len + 1 + cmdline_second_len + 1 + cmdline_extra_len;
217*d289c2baSAndroid Build Coastguard Worker   err = uefi_call_wrapper(BS->AllocatePool,
218*d289c2baSAndroid Build Coastguard Worker                           NUM_ARGS_ALLOCATE_POOL,
219*d289c2baSAndroid Build Coastguard Worker                           EfiLoaderCode,
220*d289c2baSAndroid Build Coastguard Worker                           cmdline_utf8_len,
221*d289c2baSAndroid Build Coastguard Worker                           &cmdline_utf8);
222*d289c2baSAndroid Build Coastguard Worker   if (EFI_ERROR(err)) {
223*d289c2baSAndroid Build Coastguard Worker     avb_error("Could not allocate kernel cmdline.\n");
224*d289c2baSAndroid Build Coastguard Worker     ret = UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_OOM;
225*d289c2baSAndroid Build Coastguard Worker     goto out;
226*d289c2baSAndroid Build Coastguard Worker   }
227*d289c2baSAndroid Build Coastguard Worker   offset = 0;
228*d289c2baSAndroid Build Coastguard Worker   avb_memcpy(cmdline_utf8, header->cmdline, cmdline_first_len);
229*d289c2baSAndroid Build Coastguard Worker   offset += cmdline_first_len;
230*d289c2baSAndroid Build Coastguard Worker   cmdline_utf8[offset] = ' ';
231*d289c2baSAndroid Build Coastguard Worker   offset += 1;
232*d289c2baSAndroid Build Coastguard Worker   avb_memcpy(cmdline_utf8 + offset, slot_data->cmdline, cmdline_second_len);
233*d289c2baSAndroid Build Coastguard Worker   offset += cmdline_second_len;
234*d289c2baSAndroid Build Coastguard Worker   if (cmdline_extra_len > 0) {
235*d289c2baSAndroid Build Coastguard Worker     cmdline_utf8[offset] = ' ';
236*d289c2baSAndroid Build Coastguard Worker     avb_memcpy(cmdline_utf8 + offset + 1, cmdline_extra, cmdline_extra_len - 1);
237*d289c2baSAndroid Build Coastguard Worker     offset += cmdline_extra_len;
238*d289c2baSAndroid Build Coastguard Worker   }
239*d289c2baSAndroid Build Coastguard Worker   cmdline_utf8[offset] = '\0';
240*d289c2baSAndroid Build Coastguard Worker   offset += 1;
241*d289c2baSAndroid Build Coastguard Worker   avb_assert(offset == cmdline_utf8_len);
242*d289c2baSAndroid Build Coastguard Worker 
243*d289c2baSAndroid Build Coastguard Worker   /* Now set up the EFI handover. */
244*d289c2baSAndroid Build Coastguard Worker   image_setup = (struct SetupHeader*)kernel_buf;
245*d289c2baSAndroid Build Coastguard Worker   if (image_setup->signature != 0xAA55 || image_setup->header != SETUP_MAGIC) {
246*d289c2baSAndroid Build Coastguard Worker     avb_error("Wrong kernel header magic.\n");
247*d289c2baSAndroid Build Coastguard Worker     ret = UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_KERNEL_INVALID_FORMAT;
248*d289c2baSAndroid Build Coastguard Worker     goto out;
249*d289c2baSAndroid Build Coastguard Worker   }
250*d289c2baSAndroid Build Coastguard Worker 
251*d289c2baSAndroid Build Coastguard Worker   if (image_setup->version < 0x20b) {
252*d289c2baSAndroid Build Coastguard Worker     avb_error("Wrong version.\n");
253*d289c2baSAndroid Build Coastguard Worker     ret = UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_KERNEL_INVALID_FORMAT;
254*d289c2baSAndroid Build Coastguard Worker     goto out;
255*d289c2baSAndroid Build Coastguard Worker   }
256*d289c2baSAndroid Build Coastguard Worker 
257*d289c2baSAndroid Build Coastguard Worker   if (!image_setup->relocatable_kernel) {
258*d289c2baSAndroid Build Coastguard Worker     avb_error("Kernel is not relocatable.\n");
259*d289c2baSAndroid Build Coastguard Worker     ret = UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_KERNEL_INVALID_FORMAT;
260*d289c2baSAndroid Build Coastguard Worker     goto out;
261*d289c2baSAndroid Build Coastguard Worker   }
262*d289c2baSAndroid Build Coastguard Worker 
263*d289c2baSAndroid Build Coastguard Worker   addr = 0x3fffffff;
264*d289c2baSAndroid Build Coastguard Worker   err = uefi_call_wrapper(BS->AllocatePages,
265*d289c2baSAndroid Build Coastguard Worker                           4,
266*d289c2baSAndroid Build Coastguard Worker                           AllocateMaxAddress,
267*d289c2baSAndroid Build Coastguard Worker                           EfiLoaderData,
268*d289c2baSAndroid Build Coastguard Worker                           EFI_SIZE_TO_PAGES(0x4000),
269*d289c2baSAndroid Build Coastguard Worker                           &addr);
270*d289c2baSAndroid Build Coastguard Worker   if (EFI_ERROR(err)) {
271*d289c2baSAndroid Build Coastguard Worker     avb_error("Could not allocate setup buffer.\n");
272*d289c2baSAndroid Build Coastguard Worker     ret = UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_OOM;
273*d289c2baSAndroid Build Coastguard Worker     goto out;
274*d289c2baSAndroid Build Coastguard Worker   }
275*d289c2baSAndroid Build Coastguard Worker   setup = (struct SetupHeader*)(UINTN)addr;
276*d289c2baSAndroid Build Coastguard Worker   avb_memset(setup, '\0', 0x4000);
277*d289c2baSAndroid Build Coastguard Worker   avb_memcpy(setup, image_setup, sizeof(struct SetupHeader));
278*d289c2baSAndroid Build Coastguard Worker   setup->loader_id = 0xff;
279*d289c2baSAndroid Build Coastguard Worker   setup->code32_start =
280*d289c2baSAndroid Build Coastguard Worker       ((uintptr_t)kernel_buf) + (image_setup->setup_secs + 1) * 512;
281*d289c2baSAndroid Build Coastguard Worker   setup->cmd_line_ptr = (uintptr_t)cmdline_utf8;
282*d289c2baSAndroid Build Coastguard Worker 
283*d289c2baSAndroid Build Coastguard Worker   setup->ramdisk_start = (uintptr_t)initramfs_buf;
284*d289c2baSAndroid Build Coastguard Worker   setup->ramdisk_len = (uintptr_t)initramfs_size;
285*d289c2baSAndroid Build Coastguard Worker 
286*d289c2baSAndroid Build Coastguard Worker   /* Jump to the kernel. */
287*d289c2baSAndroid Build Coastguard Worker   linux_efi_handover(efi_image_handle, setup);
288*d289c2baSAndroid Build Coastguard Worker 
289*d289c2baSAndroid Build Coastguard Worker   ret = UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_START_KERNEL;
290*d289c2baSAndroid Build Coastguard Worker out:
291*d289c2baSAndroid Build Coastguard Worker   return ret;
292*d289c2baSAndroid Build Coastguard Worker }
293*d289c2baSAndroid Build Coastguard Worker 
uefi_avb_boot_kernel_result_to_string(UEFIAvbBootKernelResult result)294*d289c2baSAndroid Build Coastguard Worker const char* uefi_avb_boot_kernel_result_to_string(
295*d289c2baSAndroid Build Coastguard Worker     UEFIAvbBootKernelResult result) {
296*d289c2baSAndroid Build Coastguard Worker   const char* ret = NULL;
297*d289c2baSAndroid Build Coastguard Worker 
298*d289c2baSAndroid Build Coastguard Worker   switch (result) {
299*d289c2baSAndroid Build Coastguard Worker     case UEFI_AVB_BOOT_KERNEL_RESULT_OK:
300*d289c2baSAndroid Build Coastguard Worker       ret = "OK";
301*d289c2baSAndroid Build Coastguard Worker       break;
302*d289c2baSAndroid Build Coastguard Worker     case UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_OOM:
303*d289c2baSAndroid Build Coastguard Worker       ret = "ERROR_OEM";
304*d289c2baSAndroid Build Coastguard Worker       break;
305*d289c2baSAndroid Build Coastguard Worker     case UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_IO:
306*d289c2baSAndroid Build Coastguard Worker       ret = "ERROR_IO";
307*d289c2baSAndroid Build Coastguard Worker       break;
308*d289c2baSAndroid Build Coastguard Worker     case UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_PARTITION_INVALID_FORMAT:
309*d289c2baSAndroid Build Coastguard Worker       ret = "ERROR_PARTITION_INVALID_FORMAT";
310*d289c2baSAndroid Build Coastguard Worker       break;
311*d289c2baSAndroid Build Coastguard Worker     case UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_KERNEL_INVALID_FORMAT:
312*d289c2baSAndroid Build Coastguard Worker       ret = "ERROR_KERNEL_INVALID_FORMAT";
313*d289c2baSAndroid Build Coastguard Worker       break;
314*d289c2baSAndroid Build Coastguard Worker     case UEFI_AVB_BOOT_KERNEL_RESULT_ERROR_START_KERNEL:
315*d289c2baSAndroid Build Coastguard Worker       ret = "ERROR_START_KERNEL";
316*d289c2baSAndroid Build Coastguard Worker       break;
317*d289c2baSAndroid Build Coastguard Worker       /* Do not add a 'default:' case here because of -Wswitch. */
318*d289c2baSAndroid Build Coastguard Worker   }
319*d289c2baSAndroid Build Coastguard Worker 
320*d289c2baSAndroid Build Coastguard Worker   if (ret == NULL) {
321*d289c2baSAndroid Build Coastguard Worker     avb_error("Unknown UEFIAvbBootKernelResult value.\n");
322*d289c2baSAndroid Build Coastguard Worker     ret = "(unknown)";
323*d289c2baSAndroid Build Coastguard Worker   }
324*d289c2baSAndroid Build Coastguard Worker 
325*d289c2baSAndroid Build Coastguard Worker   return ret;
326*d289c2baSAndroid Build Coastguard Worker }
327