]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
0fa2cac4 KS |
2 | |
3 | #include <efi.h> | |
4 | #include <efilib.h> | |
5 | ||
0fa2cac4 | 6 | #include "linux.h" |
cf0fbc49 | 7 | #include "util.h" |
0fa2cac4 | 8 | |
4287d083 DS |
9 | #ifdef __i386__ |
10 | #define __regparm0__ __attribute__((regparm(0))) | |
0fa2cac4 | 11 | #else |
4287d083 DS |
12 | #define __regparm0__ |
13 | #endif | |
14 | ||
15 | typedef VOID(*handover_f)(VOID *image, EFI_SYSTEM_TABLE *table, struct boot_params *params) __regparm0__; | |
6247c336 | 16 | static VOID linux_efi_handover(EFI_HANDLE image, struct boot_params *params) { |
0fa2cac4 | 17 | handover_f handover; |
4287d083 | 18 | UINTN start = (UINTN)params->hdr.code32_start; |
0fa2cac4 | 19 | |
4287d083 DS |
20 | #ifdef __x86_64__ |
21 | asm volatile ("cli"); | |
22 | start += 512; | |
23 | #endif | |
24 | handover = (handover_f)(start + params->hdr.handover_offset); | |
6247c336 | 25 | handover(image, ST, params); |
0fa2cac4 | 26 | } |
0fa2cac4 KS |
27 | |
28 | EFI_STATUS linux_exec(EFI_HANDLE *image, | |
29 | CHAR8 *cmdline, UINTN cmdline_len, | |
30 | UINTN linux_addr, | |
5f7df68c | 31 | UINTN initrd_addr, UINTN initrd_size) { |
6247c336 MN |
32 | struct boot_params *image_params; |
33 | struct boot_params *boot_params; | |
34 | UINT8 setup_sectors; | |
0fa2cac4 KS |
35 | EFI_PHYSICAL_ADDRESS addr; |
36 | EFI_STATUS err; | |
37 | ||
6247c336 | 38 | image_params = (struct boot_params *) linux_addr; |
0fa2cac4 | 39 | |
6247c336 MN |
40 | if (image_params->hdr.boot_flag != 0xAA55 || |
41 | image_params->hdr.header != SETUP_MAGIC || | |
42 | image_params->hdr.version < 0x20b || | |
43 | !image_params->hdr.relocatable_kernel) | |
0fa2cac4 KS |
44 | return EFI_LOAD_ERROR; |
45 | ||
6247c336 | 46 | boot_params = (struct boot_params *) 0xFFFFFFFF; |
0fa2cac4 | 47 | err = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress, EfiLoaderData, |
0a71e31c | 48 | EFI_SIZE_TO_PAGES(0x4000), (EFI_PHYSICAL_ADDRESS*) &boot_params); |
0fa2cac4 KS |
49 | if (EFI_ERROR(err)) |
50 | return err; | |
0fa2cac4 | 51 | |
6247c336 MN |
52 | ZeroMem(boot_params, 0x4000); |
53 | CopyMem(&boot_params->hdr, &image_params->hdr, sizeof(struct setup_header)); | |
54 | boot_params->hdr.type_of_loader = 0xff; | |
55 | setup_sectors = image_params->hdr.setup_sects > 0 ? image_params->hdr.setup_sects : 4; | |
56 | boot_params->hdr.code32_start = (UINT32)linux_addr + (setup_sectors + 1) * 512; | |
0fa2cac4 KS |
57 | |
58 | if (cmdline) { | |
59 | addr = 0xA0000; | |
60 | err = uefi_call_wrapper(BS->AllocatePages, 4, AllocateMaxAddress, EfiLoaderData, | |
61 | EFI_SIZE_TO_PAGES(cmdline_len + 1), &addr); | |
62 | if (EFI_ERROR(err)) | |
63 | return err; | |
64 | CopyMem((VOID *)(UINTN)addr, cmdline, cmdline_len); | |
33de6b57 | 65 | ((CHAR8 *)(UINTN)addr)[cmdline_len] = 0; |
6247c336 | 66 | boot_params->hdr.cmd_line_ptr = (UINT32)addr; |
0fa2cac4 KS |
67 | } |
68 | ||
6247c336 MN |
69 | boot_params->hdr.ramdisk_image = (UINT32)initrd_addr; |
70 | boot_params->hdr.ramdisk_size = (UINT32)initrd_size; | |
0fa2cac4 | 71 | |
6247c336 | 72 | linux_efi_handover(image, boot_params); |
0fa2cac4 KS |
73 | return EFI_LOAD_ERROR; |
74 | } |