2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU Lesser General Public License as published by
4 * the Free Software Foundation; either version 2.1 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
12 * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
21 #define SETUP_MAGIC 0x53726448 /* "HdrS" */
23 UINT8 boot_sector
[0x01f1];
44 UINT32 bootsect_kludge
;
47 UINT8 ext_loader_type
;
50 UINT32 kernel_alignment
;
51 UINT8 relocatable_kernel
;
55 UINT32 hardware_subarch
;
56 UINT64 hardware_subarch_data
;
57 UINT32 payload_offset
;
58 UINT32 payload_length
;
62 UINT32 handover_offset
;
63 } __attribute__((packed
));
66 typedef VOID(*handover_f
)(VOID
*image
, EFI_SYSTEM_TABLE
*table
, struct SetupHeader
*setup
);
67 static inline VOID
linux_efi_handover(EFI_HANDLE image
, struct SetupHeader
*setup
) {
71 handover
= (handover_f
)((UINTN
)setup
->code32_start
+ 512 + setup
->handover_offset
);
72 handover(image
, ST
, setup
);
75 typedef VOID(*handover_f
)(VOID
*image
, EFI_SYSTEM_TABLE
*table
, struct SetupHeader
*setup
) __attribute__((regparm(0)));
76 static inline VOID
linux_efi_handover(EFI_HANDLE image
, struct SetupHeader
*setup
) {
79 handover
= (handover_f
)((UINTN
)setup
->code32_start
+ setup
->handover_offset
);
80 handover(image
, ST
, setup
);
84 EFI_STATUS
linux_exec(EFI_HANDLE
*image
,
85 CHAR8
*cmdline
, UINTN cmdline_len
,
87 UINTN initrd_addr
, UINTN initrd_size
) {
88 struct SetupHeader
*image_setup
;
89 struct SetupHeader
*boot_setup
;
90 EFI_PHYSICAL_ADDRESS addr
;
93 image_setup
= (struct SetupHeader
*)(linux_addr
);
94 if (image_setup
->signature
!= 0xAA55 || image_setup
->header
!= SETUP_MAGIC
)
95 return EFI_LOAD_ERROR
;
97 if (image_setup
->version
< 0x20b || !image_setup
->relocatable_kernel
)
98 return EFI_LOAD_ERROR
;
101 err
= uefi_call_wrapper(BS
->AllocatePages
, 4, AllocateMaxAddress
, EfiLoaderData
,
102 EFI_SIZE_TO_PAGES(0x4000), &addr
);
105 boot_setup
= (struct SetupHeader
*)(UINTN
)addr
;
106 ZeroMem(boot_setup
, 0x4000);
107 CopyMem(boot_setup
, image_setup
, sizeof(struct SetupHeader
));
108 boot_setup
->loader_id
= 0xff;
110 boot_setup
->code32_start
= (UINT32
)linux_addr
+ (image_setup
->setup_secs
+1) * 512;
114 err
= uefi_call_wrapper(BS
->AllocatePages
, 4, AllocateMaxAddress
, EfiLoaderData
,
115 EFI_SIZE_TO_PAGES(cmdline_len
+ 1), &addr
);
118 CopyMem((VOID
*)(UINTN
)addr
, cmdline
, cmdline_len
);
119 ((CHAR8
*)addr
)[cmdline_len
] = 0;
120 boot_setup
->cmd_line_ptr
= (UINT32
)addr
;
123 boot_setup
->ramdisk_start
= (UINT32
)initrd_addr
;
124 boot_setup
->ramdisk_len
= (UINT32
)initrd_size
;
126 linux_efi_handover(image
, boot_setup
);
127 return EFI_LOAD_ERROR
;