Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitec80b47

Browse files
apalosxypron
authored andcommitted
efi_loader: Implement FileLoad2 for initramfs loading
Following kernel's proposal for an arch-agnostic initrd loadingmechanism [1] let's implement the U-boot counterpart.This new approach has a number of advantages compared to what we did upto now. The file is loaded into memory only when requested limiting thearea of TOCTOU attacks. Users will be allowed to place the initramfsfile on any u-boot accessible partition instead of just the ESP one.Finally this is an attempt of a generic interface across architecturesin the linux kernel so it makes sense to support that.The file location is intentionally only supported as a config optionargument(CONFIG_EFI_INITRD_FILESPEC), in an effort to enhance security.Although U-boot is not responsible for verifying the integrity of theinitramfs, we can enhance the offered security by only accepting abuilt-in option, which will be naturally verified by UEFI Secure Boot.This can easily change in the future if needed and configure that via ENVor UEFI variable.[1]https://lore.kernel.org/linux-efi/20200207202637.GA3464906@rani.riverdale.lan/T/#m4a25eb33112fab7a22faa0fd65d4d663209af32fSigned-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
1 parent12fdbbe commitec80b47

File tree

8 files changed

+266
-0
lines changed

8 files changed

+266
-0
lines changed

‎cmd/efidebug.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ static const struct {
243243
"HII Config Routing",
244244
EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID,
245245
},
246+
{
247+
"Load File2",
248+
EFI_LOAD_FILE2_PROTOCOL_GUID,
249+
},
246250
{
247251
"Simple Network",
248252
EFI_SIMPLE_NETWORK_PROTOCOL_GUID,

‎include/efi_api.h‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,14 @@ struct efi_runtime_services {
331331
EFI_GUID(0xeb9d2d31, 0x2d88, 0x11d3, \
332332
0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
333333

334+
#defineEFI_LOAD_FILE_PROTOCOL_GUID \
335+
EFI_GUID(0x56ec3091, 0x954c, 0x11d2, \
336+
0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
337+
338+
#defineEFI_LOAD_FILE2_PROTOCOL_GUID \
339+
EFI_GUID(0x4006c0c1, 0xfcb3, 0x403e, \
340+
0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d)
341+
334342
structefi_configuration_table {
335343
efi_guid_tguid;
336344
void*table;
@@ -486,6 +494,7 @@ struct efi_device_path_nvme {
486494
#defineDEVICE_PATH_TYPE_MEDIA_DEVICE0x04
487495
# defineDEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH0x01
488496
# defineDEVICE_PATH_SUB_TYPE_CDROM_PATH0x02
497+
# defineDEVICE_PATH_SUB_TYPE_VENDOR_PATH0x03
489498
# defineDEVICE_PATH_SUB_TYPE_FILE_PATH0x04
490499

491500
structefi_device_path_hard_drive_path {
@@ -1619,6 +1628,14 @@ struct efi_unicode_collation_protocol {
16191628
char*supported_languages;
16201629
};
16211630

1631+
structefi_load_file_protocol {
1632+
efi_status_t (EFIAPI*load_file)(structefi_load_file_protocol*this,
1633+
structefi_device_path*file_path,
1634+
boolboot_policy,
1635+
efi_uintn_t*buffer_size,
1636+
void*buffer);
1637+
};
1638+
16221639
/* Boot manager load options */
16231640
#defineLOAD_OPTION_ACTIVE0x00000001
16241641
#defineLOAD_OPTION_FORCE_RECONNECT0x00000002

‎include/efi_load_initrd.h‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* SPDX-License-Identifier: GPL-2.0+ */
2+
/*
3+
* Copyright (c) 2020, Linaro Limited
4+
*/
5+
6+
#if !defined_EFI_LOAD_INITRD_H_
7+
#define_EFI_LOAD_INITRD_H_
8+
9+
#include<efi.h>
10+
#include<efi_api.h>
11+
12+
/*
13+
* Vendor GUID used by Linux to identify the handle with the
14+
* EFI_LOAD_FILE2_PROTOCOL and load an initial ramdisk.
15+
*/
16+
#defineEFI_INITRD_MEDIA_GUID \
17+
EFI_GUID(0x5568e427, 0x68fc, 0x4f3d, \
18+
0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68)
19+
20+
structefi_initrd_dp {
21+
structefi_device_path_vendorvendor;
22+
structefi_device_pathend;
23+
}__packed;
24+
25+
#endif

‎include/efi_loader.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ efi_status_t efi_gop_register(void);
378378
efi_status_tefi_net_register(void);
379379
/* Called by bootefi to make the watchdog available */
380380
efi_status_tefi_watchdog_register(void);
381+
efi_status_tefi_initrd_register(void);
381382
/* Called by bootefi to make SMBIOS tables available */
382383
/**
383384
* efi_acpi_register() - write out ACPI tables

‎lib/efi_loader/Kconfig‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,19 @@ config EFI_RNG_PROTOCOL
130130
Provide a EFI_RNG_PROTOCOL implementation using the hardware random
131131
number generator of the platform.
132132

133+
config EFI_LOAD_FILE2_INITRD
134+
bool "EFI_FILE_LOAD2_PROTOCOL for Linux initial ramdisk"
135+
default n
136+
help
137+
Expose a EFI_FILE_LOAD2_PROTOCOL that the Linux UEFI stub can
138+
use to load the initial ramdisk. Once this is enabled using
139+
initrd=<ramdisk> will stop working.
140+
141+
config EFI_INITRD_FILESPEC
142+
string "initramfs path"
143+
default "host 0:1 initrd"
144+
depends on EFI_LOAD_FILE2_INITRD
145+
help
146+
Full path of the initramfs file, e.g. mmc 0:2 initramfs.cpio.gz.
147+
133148
endif

‎lib/efi_loader/Makefile‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,4 @@ obj-$(CONFIG_NET) += efi_net.o
4343
obj-$(CONFIG_GENERATE_ACPI_TABLE) += efi_acpi.o
4444
obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o
4545
obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_rng.o
46+
obj-$(CONFIG_EFI_LOAD_FILE2_INITRD) += efi_load_initrd.o

‎lib/efi_loader/efi_load_initrd.c‎

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
// SPDX-License-Identifier: GPL-2.0+
2+
/*
3+
* Copyright (c) 2020, Linaro Limited
4+
*/
5+
6+
#include<common.h>
7+
#include<env.h>
8+
#include<malloc.h>
9+
#include<mapmem.h>
10+
#include<dm.h>
11+
#include<fs.h>
12+
#include<efi_loader.h>
13+
#include<efi_load_initrd.h>
14+
15+
staticconstefi_guid_tefi_guid_load_file2_protocol=
16+
EFI_LOAD_FILE2_PROTOCOL_GUID;
17+
18+
staticefi_status_tEFIAPI
19+
efi_load_file2_initrd(structefi_load_file_protocol*this,
20+
structefi_device_path*file_path,boolboot_policy,
21+
efi_uintn_t*buffer_size,void*buffer);
22+
23+
staticconststructefi_load_file_protocolefi_lf2_protocol= {
24+
.load_file=efi_load_file2_initrd,
25+
};
26+
27+
/*
28+
* Device path defined by Linux to identify the handle providing the
29+
* EFI_LOAD_FILE2_PROTOCOL used for loading the initial ramdisk.
30+
*/
31+
staticconststructefi_initrd_dpdp= {
32+
.vendor= {
33+
{
34+
DEVICE_PATH_TYPE_MEDIA_DEVICE,
35+
DEVICE_PATH_SUB_TYPE_VENDOR_PATH,
36+
sizeof(dp.vendor),
37+
},
38+
EFI_INITRD_MEDIA_GUID,
39+
},
40+
.end= {
41+
DEVICE_PATH_TYPE_END,
42+
DEVICE_PATH_SUB_TYPE_END,
43+
sizeof(dp.end),
44+
}
45+
};
46+
47+
/**
48+
* get_file_size() - retrieve the size of initramfs, set efi status on error
49+
*
50+
* @dev:device to read from. i.e "mmc"
51+
* @part:device partition. i.e "0:1"
52+
* @file:name fo file
53+
* @status:EFI exit code in case of failure
54+
*
55+
* Return:size of file
56+
*/
57+
staticloff_tget_file_size(constchar*dev,constchar*part,constchar*file,
58+
efi_status_t*status)
59+
{
60+
loff_tsz=0;
61+
intret;
62+
63+
ret=fs_set_blk_dev(dev,part,FS_TYPE_ANY);
64+
if (ret) {
65+
*status=EFI_NO_MEDIA;
66+
gotoout;
67+
}
68+
69+
ret=fs_size(file,&sz);
70+
if (ret) {
71+
sz=0;
72+
*status=EFI_NOT_FOUND;
73+
gotoout;
74+
}
75+
76+
out:
77+
returnsz;
78+
}
79+
80+
/**
81+
* load_file2() - get information about random number generation
82+
*
83+
* This function implement the LoadFile2() service in order to load an initram
84+
* disk requested by the Linux kernel stub.
85+
* See the UEFI spec for details.
86+
*
87+
* @this:loadfile2 protocol instance
88+
* @file_path:relative path of the file. "" in this case
89+
* @boot_policy:must be false for Loadfile2
90+
* @buffer_size:size of allocated buffer
91+
* @buffer:buffer to load the file
92+
*
93+
* Return:status code
94+
*/
95+
staticefi_status_tEFIAPI
96+
efi_load_file2_initrd(structefi_load_file_protocol*this,
97+
structefi_device_path*file_path,boolboot_policy,
98+
efi_uintn_t*buffer_size,void*buffer)
99+
{
100+
constchar*filespec=CONFIG_EFI_INITRD_FILESPEC;
101+
efi_status_tstatus=EFI_NOT_FOUND;
102+
loff_tfile_sz=0,read_sz=0;
103+
char*dev,*part,*file;
104+
char*s;
105+
intret;
106+
107+
EFI_ENTRY("%p, %p, %d, %p, %p",this,file_path,boot_policy,
108+
buffer_size,buffer);
109+
110+
s=strdup(filespec);
111+
if (!s)
112+
gotoout;
113+
114+
if (!this||this!=&efi_lf2_protocol||
115+
!buffer_size) {
116+
status=EFI_INVALID_PARAMETER;
117+
gotoout;
118+
}
119+
120+
if (file_path->type!=dp.end.type||
121+
file_path->sub_type!=dp.end.sub_type) {
122+
status=EFI_INVALID_PARAMETER;
123+
gotoout;
124+
}
125+
126+
if (boot_policy) {
127+
status=EFI_UNSUPPORTED;
128+
gotoout;
129+
}
130+
131+
/* expect something like 'mmc 0:1 initrd.cpio.gz' */
132+
dev=strsep(&s," ");
133+
if (!dev)
134+
gotoout;
135+
part=strsep(&s," ");
136+
if (!part)
137+
gotoout;
138+
file=strsep(&s," ");
139+
if (!file)
140+
gotoout;
141+
142+
file_sz=get_file_size(dev,part,file,&status);
143+
if (!file_sz)
144+
gotoout;
145+
146+
if (!buffer||*buffer_size<file_sz) {
147+
status=EFI_BUFFER_TOO_SMALL;
148+
*buffer_size=file_sz;
149+
}else {
150+
ret=fs_set_blk_dev(dev,part,FS_TYPE_ANY);
151+
if (ret) {
152+
status=EFI_NO_MEDIA;
153+
gotoout;
154+
}
155+
156+
ret=fs_read(file,map_to_sysmem(buffer),0,*buffer_size,
157+
&read_sz);
158+
if (ret||read_sz!=file_sz)
159+
gotoout;
160+
*buffer_size=read_sz;
161+
162+
status=EFI_SUCCESS;
163+
}
164+
165+
out:
166+
free(s);
167+
returnEFI_EXIT(status);
168+
}
169+
170+
/**
171+
* efi_initrd_register() - Register a handle and loadfile2 protocol
172+
*
173+
* This function creates a new handle and installs a linux specific GUID
174+
* to handle initram disk loading during boot.
175+
* See the UEFI spec for details.
176+
*
177+
* Return:status code
178+
*/
179+
efi_status_tefi_initrd_register(void)
180+
{
181+
efi_handle_tefi_initrd_handle=NULL;
182+
efi_status_tret;
183+
184+
/*
185+
* Set up the handle with the EFI_LOAD_FILE2_PROTOCOL which Linux may
186+
* use to load the initial ramdisk.
187+
*/
188+
ret=EFI_CALL(efi_install_multiple_protocol_interfaces
189+
(&efi_initrd_handle,
190+
/* initramfs */
191+
&efi_guid_device_path,&dp,
192+
/* LOAD_FILE2 */
193+
&efi_guid_load_file2_protocol,
194+
(void*)&efi_lf2_protocol,
195+
NULL));
196+
197+
returnret;
198+
}

‎lib/efi_loader/efi_setup.c‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,11 @@ efi_status_t efi_init_obj_list(void)
155155
if (ret!=EFI_SUCCESS)
156156
gotoout;
157157
#endif
158+
#ifdefCONFIG_EFI_LOAD_FILE2_INITRD
159+
ret=efi_initrd_register();
160+
if (ret!=EFI_SUCCESS)
161+
gotoout;
162+
#endif
158163
#ifdefCONFIG_NET
159164
ret=efi_net_register();
160165
if (ret!=EFI_SUCCESS)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp