Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
3203209d
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
3203209d
编写于
9月 25, 2013
作者:
M
Matt Fleming
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'arm/common' into next
上级
9efff389
4e283088
变更
6
显示空白变更内容
内联
并排
Showing
6 changed file
with
712 addition
and
567 deletion
+712
-567
Documentation/efi-stub.txt
Documentation/efi-stub.txt
+0
-0
arch/x86/Kconfig
arch/x86/Kconfig
+1
-1
arch/x86/boot/compressed/eboot.c
arch/x86/boot/compressed/eboot.c
+39
-541
arch/x86/boot/compressed/eboot.h
arch/x86/boot/compressed/eboot.h
+0
-9
drivers/firmware/efi/efi-stub-helper.c
drivers/firmware/efi/efi-stub-helper.c
+638
-0
include/linux/efi.h
include/linux/efi.h
+34
-16
未找到文件。
Documentation/
x86/
efi-stub.txt
→
Documentation/efi-stub.txt
浏览文件 @
3203209d
文件已移动
arch/x86/Kconfig
浏览文件 @
3203209d
...
@@ -1579,7 +1579,7 @@ config EFI_STUB
...
@@ -1579,7 +1579,7 @@ config EFI_STUB
This kernel feature allows a bzImage to be loaded directly
This kernel feature allows a bzImage to be loaded directly
by EFI firmware without the use of a bootloader.
by EFI firmware without the use of a bootloader.
See Documentation/
x86/
efi-stub.txt for more information.
See Documentation/efi-stub.txt for more information.
config SECCOMP
config SECCOMP
def_bool y
def_bool y
...
...
arch/x86/boot/compressed/eboot.c
浏览文件 @
3203209d
...
@@ -19,214 +19,10 @@
...
@@ -19,214 +19,10 @@
static
efi_system_table_t
*
sys_table
;
static
efi_system_table_t
*
sys_table
;
static
void
efi_char16_printk
(
efi_char16_t
*
str
)
{
struct
efi_simple_text_output_protocol
*
out
;
out
=
(
struct
efi_simple_text_output_protocol
*
)
sys_table
->
con_out
;
efi_call_phys2
(
out
->
output_string
,
out
,
str
);
}
static
void
efi_printk
(
char
*
str
)
{
char
*
s8
;
for
(
s8
=
str
;
*
s8
;
s8
++
)
{
efi_char16_t
ch
[
2
]
=
{
0
};
ch
[
0
]
=
*
s8
;
if
(
*
s8
==
'\n'
)
{
efi_char16_t
nl
[
2
]
=
{
'\r'
,
0
};
efi_char16_printk
(
nl
);
}
efi_char16_printk
(
ch
);
}
}
static
efi_status_t
__get_map
(
efi_memory_desc_t
**
map
,
unsigned
long
*
map_size
,
unsigned
long
*
desc_size
)
{
efi_memory_desc_t
*
m
=
NULL
;
efi_status_t
status
;
unsigned
long
key
;
u32
desc_version
;
*
map_size
=
sizeof
(
*
m
)
*
32
;
again:
/*
* Add an additional efi_memory_desc_t because we're doing an
* allocation which may be in a new descriptor region.
*/
*
map_size
+=
sizeof
(
*
m
);
status
=
efi_call_phys3
(
sys_table
->
boottime
->
allocate_pool
,
EFI_LOADER_DATA
,
*
map_size
,
(
void
**
)
&
m
);
if
(
status
!=
EFI_SUCCESS
)
goto
fail
;
status
=
efi_call_phys5
(
sys_table
->
boottime
->
get_memory_map
,
map_size
,
m
,
&
key
,
desc_size
,
&
desc_version
);
if
(
status
==
EFI_BUFFER_TOO_SMALL
)
{
efi_call_phys1
(
sys_table
->
boottime
->
free_pool
,
m
);
goto
again
;
}
if
(
status
!=
EFI_SUCCESS
)
efi_call_phys1
(
sys_table
->
boottime
->
free_pool
,
m
);
fail:
*
map
=
m
;
return
status
;
}
/*
* Allocate at the highest possible address that is not above 'max'.
*/
static
efi_status_t
high_alloc
(
unsigned
long
size
,
unsigned
long
align
,
unsigned
long
*
addr
,
unsigned
long
max
)
{
unsigned
long
map_size
,
desc_size
;
efi_memory_desc_t
*
map
;
efi_status_t
status
;
unsigned
long
nr_pages
;
u64
max_addr
=
0
;
int
i
;
status
=
__get_map
(
&
map
,
&
map_size
,
&
desc_size
);
if
(
status
!=
EFI_SUCCESS
)
goto
fail
;
nr_pages
=
round_up
(
size
,
EFI_PAGE_SIZE
)
/
EFI_PAGE_SIZE
;
again:
for
(
i
=
0
;
i
<
map_size
/
desc_size
;
i
++
)
{
efi_memory_desc_t
*
desc
;
unsigned
long
m
=
(
unsigned
long
)
map
;
u64
start
,
end
;
desc
=
(
efi_memory_desc_t
*
)(
m
+
(
i
*
desc_size
));
if
(
desc
->
type
!=
EFI_CONVENTIONAL_MEMORY
)
continue
;
if
(
desc
->
num_pages
<
nr_pages
)
continue
;
start
=
desc
->
phys_addr
;
end
=
start
+
desc
->
num_pages
*
(
1UL
<<
EFI_PAGE_SHIFT
);
if
((
start
+
size
)
>
end
||
(
start
+
size
)
>
max
)
continue
;
if
(
end
-
size
>
max
)
end
=
max
;
if
(
round_down
(
end
-
size
,
align
)
<
start
)
continue
;
start
=
round_down
(
end
-
size
,
align
);
/*
* Don't allocate at 0x0. It will confuse code that
* checks pointers against NULL.
*/
if
(
start
==
0x0
)
continue
;
if
(
start
>
max_addr
)
max_addr
=
start
;
}
if
(
!
max_addr
)
status
=
EFI_NOT_FOUND
;
else
{
status
=
efi_call_phys4
(
sys_table
->
boottime
->
allocate_pages
,
EFI_ALLOCATE_ADDRESS
,
EFI_LOADER_DATA
,
nr_pages
,
&
max_addr
);
if
(
status
!=
EFI_SUCCESS
)
{
max
=
max_addr
;
max_addr
=
0
;
goto
again
;
}
*
addr
=
max_addr
;
}
free_pool:
efi_call_phys1
(
sys_table
->
boottime
->
free_pool
,
map
);
fail:
return
status
;
}
/*
* Allocate at the lowest possible address.
*/
static
efi_status_t
low_alloc
(
unsigned
long
size
,
unsigned
long
align
,
unsigned
long
*
addr
)
{
unsigned
long
map_size
,
desc_size
;
efi_memory_desc_t
*
map
;
efi_status_t
status
;
unsigned
long
nr_pages
;
int
i
;
status
=
__get_map
(
&
map
,
&
map_size
,
&
desc_size
);
if
(
status
!=
EFI_SUCCESS
)
goto
fail
;
nr_pages
=
round_up
(
size
,
EFI_PAGE_SIZE
)
/
EFI_PAGE_SIZE
;
for
(
i
=
0
;
i
<
map_size
/
desc_size
;
i
++
)
{
efi_memory_desc_t
*
desc
;
unsigned
long
m
=
(
unsigned
long
)
map
;
u64
start
,
end
;
desc
=
(
efi_memory_desc_t
*
)(
m
+
(
i
*
desc_size
));
if
(
desc
->
type
!=
EFI_CONVENTIONAL_MEMORY
)
continue
;
if
(
desc
->
num_pages
<
nr_pages
)
continue
;
start
=
desc
->
phys_addr
;
end
=
start
+
desc
->
num_pages
*
(
1UL
<<
EFI_PAGE_SHIFT
);
/*
* Don't allocate at 0x0. It will confuse code that
* checks pointers against NULL. Skip the first 8
* bytes so we start at a nice even number.
*/
if
(
start
==
0x0
)
start
+=
8
;
start
=
round_up
(
start
,
align
);
if
((
start
+
size
)
>
end
)
continue
;
status
=
efi_call_phys4
(
sys_table
->
boottime
->
allocate_pages
,
#include "../../../../drivers/firmware/efi/efi-stub-helper.c"
EFI_ALLOCATE_ADDRESS
,
EFI_LOADER_DATA
,
nr_pages
,
&
start
);
if
(
status
==
EFI_SUCCESS
)
{
*
addr
=
start
;
break
;
}
}
if
(
i
==
map_size
/
desc_size
)
status
=
EFI_NOT_FOUND
;
free_pool:
efi_call_phys1
(
sys_table
->
boottime
->
free_pool
,
map
);
fail:
return
status
;
}
static
void
low_free
(
unsigned
long
size
,
unsigned
long
addr
)
{
unsigned
long
nr_pages
;
nr_pages
=
round_up
(
size
,
EFI_PAGE_SIZE
)
/
EFI_PAGE_SIZE
;
efi_call_phys2
(
sys_table
->
boottime
->
free_pages
,
addr
,
nr_pages
);
}
static
void
find_bits
(
unsigned
long
mask
,
u8
*
pos
,
u8
*
size
)
static
void
find_bits
(
unsigned
long
mask
,
u8
*
pos
,
u8
*
size
)
{
{
...
@@ -624,242 +420,6 @@ void setup_graphics(struct boot_params *boot_params)
...
@@ -624,242 +420,6 @@ void setup_graphics(struct boot_params *boot_params)
}
}
}
}
struct
initrd
{
efi_file_handle_t
*
handle
;
u64
size
;
};
/*
* Check the cmdline for a LILO-style initrd= arguments.
*
* We only support loading an initrd from the same filesystem as the
* kernel image.
*/
static
efi_status_t
handle_ramdisks
(
efi_loaded_image_t
*
image
,
struct
setup_header
*
hdr
)
{
struct
initrd
*
initrds
;
unsigned
long
initrd_addr
;
efi_guid_t
fs_proto
=
EFI_FILE_SYSTEM_GUID
;
u64
initrd_total
;
efi_file_io_interface_t
*
io
;
efi_file_handle_t
*
fh
;
efi_status_t
status
;
int
nr_initrds
;
char
*
str
;
int
i
,
j
,
k
;
initrd_addr
=
0
;
initrd_total
=
0
;
str
=
(
char
*
)(
unsigned
long
)
hdr
->
cmd_line_ptr
;
j
=
0
;
/* See close_handles */
if
(
!
str
||
!*
str
)
return
EFI_SUCCESS
;
for
(
nr_initrds
=
0
;
*
str
;
nr_initrds
++
)
{
str
=
strstr
(
str
,
"initrd="
);
if
(
!
str
)
break
;
str
+=
7
;
/* Skip any leading slashes */
while
(
*
str
==
'/'
||
*
str
==
'\\'
)
str
++
;
while
(
*
str
&&
*
str
!=
' '
&&
*
str
!=
'\n'
)
str
++
;
}
if
(
!
nr_initrds
)
return
EFI_SUCCESS
;
status
=
efi_call_phys3
(
sys_table
->
boottime
->
allocate_pool
,
EFI_LOADER_DATA
,
nr_initrds
*
sizeof
(
*
initrds
),
&
initrds
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
"Failed to alloc mem for initrds
\n
"
);
goto
fail
;
}
str
=
(
char
*
)(
unsigned
long
)
hdr
->
cmd_line_ptr
;
for
(
i
=
0
;
i
<
nr_initrds
;
i
++
)
{
struct
initrd
*
initrd
;
efi_file_handle_t
*
h
;
efi_file_info_t
*
info
;
efi_char16_t
filename_16
[
256
];
unsigned
long
info_sz
;
efi_guid_t
info_guid
=
EFI_FILE_INFO_ID
;
efi_char16_t
*
p
;
u64
file_sz
;
str
=
strstr
(
str
,
"initrd="
);
if
(
!
str
)
break
;
str
+=
7
;
initrd
=
&
initrds
[
i
];
p
=
filename_16
;
/* Skip any leading slashes */
while
(
*
str
==
'/'
||
*
str
==
'\\'
)
str
++
;
while
(
*
str
&&
*
str
!=
' '
&&
*
str
!=
'\n'
)
{
if
((
u8
*
)
p
>=
(
u8
*
)
filename_16
+
sizeof
(
filename_16
))
break
;
if
(
*
str
==
'/'
)
{
*
p
++
=
'\\'
;
*
str
++
;
}
else
{
*
p
++
=
*
str
++
;
}
}
*
p
=
'\0'
;
/* Only open the volume once. */
if
(
!
i
)
{
efi_boot_services_t
*
boottime
;
boottime
=
sys_table
->
boottime
;
status
=
efi_call_phys3
(
boottime
->
handle_protocol
,
image
->
device_handle
,
&
fs_proto
,
&
io
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
"Failed to handle fs_proto
\n
"
);
goto
free_initrds
;
}
status
=
efi_call_phys2
(
io
->
open_volume
,
io
,
&
fh
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
"Failed to open volume
\n
"
);
goto
free_initrds
;
}
}
status
=
efi_call_phys5
(
fh
->
open
,
fh
,
&
h
,
filename_16
,
EFI_FILE_MODE_READ
,
(
u64
)
0
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
"Failed to open initrd file: "
);
efi_char16_printk
(
filename_16
);
efi_printk
(
"
\n
"
);
goto
close_handles
;
}
initrd
->
handle
=
h
;
info_sz
=
0
;
status
=
efi_call_phys4
(
h
->
get_info
,
h
,
&
info_guid
,
&
info_sz
,
NULL
);
if
(
status
!=
EFI_BUFFER_TOO_SMALL
)
{
efi_printk
(
"Failed to get initrd info size
\n
"
);
goto
close_handles
;
}
grow:
status
=
efi_call_phys3
(
sys_table
->
boottime
->
allocate_pool
,
EFI_LOADER_DATA
,
info_sz
,
&
info
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
"Failed to alloc mem for initrd info
\n
"
);
goto
close_handles
;
}
status
=
efi_call_phys4
(
h
->
get_info
,
h
,
&
info_guid
,
&
info_sz
,
info
);
if
(
status
==
EFI_BUFFER_TOO_SMALL
)
{
efi_call_phys1
(
sys_table
->
boottime
->
free_pool
,
info
);
goto
grow
;
}
file_sz
=
info
->
file_size
;
efi_call_phys1
(
sys_table
->
boottime
->
free_pool
,
info
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
"Failed to get initrd info
\n
"
);
goto
close_handles
;
}
initrd
->
size
=
file_sz
;
initrd_total
+=
file_sz
;
}
if
(
initrd_total
)
{
unsigned
long
addr
;
/*
* Multiple initrd's need to be at consecutive
* addresses in memory, so allocate enough memory for
* all the initrd's.
*/
status
=
high_alloc
(
initrd_total
,
0x1000
,
&
initrd_addr
,
hdr
->
initrd_addr_max
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
"Failed to alloc highmem for initrds
\n
"
);
goto
close_handles
;
}
/* We've run out of free low memory. */
if
(
initrd_addr
>
hdr
->
initrd_addr_max
)
{
efi_printk
(
"We've run out of free low memory
\n
"
);
status
=
EFI_INVALID_PARAMETER
;
goto
free_initrd_total
;
}
addr
=
initrd_addr
;
for
(
j
=
0
;
j
<
nr_initrds
;
j
++
)
{
u64
size
;
size
=
initrds
[
j
].
size
;
while
(
size
)
{
u64
chunksize
;
if
(
size
>
EFI_READ_CHUNK_SIZE
)
chunksize
=
EFI_READ_CHUNK_SIZE
;
else
chunksize
=
size
;
status
=
efi_call_phys3
(
fh
->
read
,
initrds
[
j
].
handle
,
&
chunksize
,
addr
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
"Failed to read initrd
\n
"
);
goto
free_initrd_total
;
}
addr
+=
chunksize
;
size
-=
chunksize
;
}
efi_call_phys1
(
fh
->
close
,
initrds
[
j
].
handle
);
}
}
efi_call_phys1
(
sys_table
->
boottime
->
free_pool
,
initrds
);
hdr
->
ramdisk_image
=
initrd_addr
;
hdr
->
ramdisk_size
=
initrd_total
;
return
status
;
free_initrd_total:
low_free
(
initrd_total
,
initrd_addr
);
close_handles:
for
(
k
=
j
;
k
<
i
;
k
++
)
efi_call_phys1
(
fh
->
close
,
initrds
[
k
].
handle
);
free_initrds:
efi_call_phys1
(
sys_table
->
boottime
->
free_pool
,
initrds
);
fail:
hdr
->
ramdisk_image
=
0
;
hdr
->
ramdisk_size
=
0
;
return
status
;
}
/*
/*
* Because the x86 boot code expects to be passed a boot_params we
* Because the x86 boot code expects to be passed a boot_params we
...
@@ -875,14 +435,15 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
...
@@ -875,14 +435,15 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
struct
efi_info
*
efi
;
struct
efi_info
*
efi
;
efi_loaded_image_t
*
image
;
efi_loaded_image_t
*
image
;
void
*
options
;
void
*
options
;
u32
load_options_size
;
efi_guid_t
proto
=
LOADED_IMAGE_PROTOCOL_GUID
;
efi_guid_t
proto
=
LOADED_IMAGE_PROTOCOL_GUID
;
int
options_size
=
0
;
int
options_size
=
0
;
efi_status_t
status
;
efi_status_t
status
;
unsigned
long
cmdline
;
char
*
cmdline_ptr
;
u16
*
s2
;
u16
*
s2
;
u8
*
s1
;
u8
*
s1
;
int
i
;
int
i
;
unsigned
long
ramdisk_addr
;
unsigned
long
ramdisk_size
;
sys_table
=
_table
;
sys_table
=
_table
;
...
@@ -893,13 +454,14 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
...
@@ -893,13 +454,14 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
status
=
efi_call_phys3
(
sys_table
->
boottime
->
handle_protocol
,
status
=
efi_call_phys3
(
sys_table
->
boottime
->
handle_protocol
,
handle
,
&
proto
,
(
void
*
)
&
image
);
handle
,
&
proto
,
(
void
*
)
&
image
);
if
(
status
!=
EFI_SUCCESS
)
{
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
"Failed to get handle for LOADED_IMAGE_PROTOCOL
\n
"
);
efi_printk
(
sys_table
,
"Failed to get handle for LOADED_IMAGE_PROTOCOL
\n
"
);
return
NULL
;
return
NULL
;
}
}
status
=
low_alloc
(
0x4000
,
1
,
(
unsigned
long
*
)
&
boot_params
);
status
=
efi_low_alloc
(
sys_table
,
0x4000
,
1
,
(
unsigned
long
*
)
&
boot_params
);
if
(
status
!=
EFI_SUCCESS
)
{
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
"Failed to alloc lowmem for boot params
\n
"
);
efi_printk
(
sys_table
,
"Failed to alloc lowmem for boot params
\n
"
);
return
NULL
;
return
NULL
;
}
}
...
@@ -926,40 +488,11 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
...
@@ -926,40 +488,11 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
hdr
->
type_of_loader
=
0x21
;
hdr
->
type_of_loader
=
0x21
;
/* Convert unicode cmdline to ascii */
/* Convert unicode cmdline to ascii */
options
=
image
->
load_options
;
cmdline_ptr
=
efi_convert_cmdline_to_ascii
(
sys_table
,
image
,
load_options_size
=
image
->
load_options_size
/
2
;
/* ASCII */
&
options_size
);
cmdline
=
0
;
if
(
!
cmdline_ptr
)
s2
=
(
u16
*
)
options
;
if
(
s2
)
{
while
(
*
s2
&&
*
s2
!=
'\n'
&&
options_size
<
load_options_size
)
{
s2
++
;
options_size
++
;
}
if
(
options_size
)
{
if
(
options_size
>
hdr
->
cmdline_size
)
options_size
=
hdr
->
cmdline_size
;
options_size
++
;
/* NUL termination */
status
=
low_alloc
(
options_size
,
1
,
&
cmdline
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
"Failed to alloc mem for cmdline
\n
"
);
goto
fail
;
goto
fail
;
}
hdr
->
cmd_line_ptr
=
(
unsigned
long
)
cmdline_ptr
;
s1
=
(
u8
*
)(
unsigned
long
)
cmdline
;
s2
=
(
u16
*
)
options
;
for
(
i
=
0
;
i
<
options_size
-
1
;
i
++
)
*
s1
++
=
*
s2
++
;
*
s1
=
'\0'
;
}
}
hdr
->
cmd_line_ptr
=
cmdline
;
hdr
->
ramdisk_image
=
0
;
hdr
->
ramdisk_image
=
0
;
hdr
->
ramdisk_size
=
0
;
hdr
->
ramdisk_size
=
0
;
...
@@ -969,16 +502,20 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
...
@@ -969,16 +502,20 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
memset
(
sdt
,
0
,
sizeof
(
*
sdt
));
memset
(
sdt
,
0
,
sizeof
(
*
sdt
));
status
=
handle_ramdisks
(
image
,
hdr
);
status
=
handle_cmdline_files
(
sys_table
,
image
,
(
char
*
)(
unsigned
long
)
hdr
->
cmd_line_ptr
,
"initrd="
,
hdr
->
initrd_addr_max
,
&
ramdisk_addr
,
&
ramdisk_size
);
if
(
status
!=
EFI_SUCCESS
)
if
(
status
!=
EFI_SUCCESS
)
goto
fail2
;
goto
fail2
;
hdr
->
ramdisk_image
=
ramdisk_addr
;
hdr
->
ramdisk_size
=
ramdisk_size
;
return
boot_params
;
return
boot_params
;
fail2:
fail2:
if
(
options_size
)
efi_free
(
sys_table
,
options_size
,
hdr
->
cmd_line_ptr
);
low_free
(
options_size
,
hdr
->
cmd_line_ptr
);
fail:
fail:
low_free
(
0x4000
,
(
unsigned
long
)
boot_params
);
efi_free
(
sys_table
,
0x4000
,
(
unsigned
long
)
boot_params
);
return
NULL
;
return
NULL
;
}
}
...
@@ -996,25 +533,12 @@ static efi_status_t exit_boot(struct boot_params *boot_params,
...
@@ -996,25 +533,12 @@ static efi_status_t exit_boot(struct boot_params *boot_params,
u8
nr_entries
;
u8
nr_entries
;
int
i
;
int
i
;
size
=
sizeof
(
*
mem_map
)
*
32
;
again:
size
+=
sizeof
(
*
mem_map
)
*
2
;
_size
=
size
;
status
=
low_alloc
(
size
,
1
,
(
unsigned
long
*
)
&
mem_map
);
if
(
status
!=
EFI_SUCCESS
)
return
status
;
get_map:
get_map:
status
=
efi_call_phys5
(
sys_table
->
boottime
->
get_memory_map
,
&
size
,
status
=
efi_get_memory_map
(
sys_table
,
&
mem_map
,
&
size
,
&
desc_size
,
mem_map
,
&
key
,
&
desc_size
,
&
desc_version
);
&
desc_version
,
&
key
);
if
(
status
==
EFI_BUFFER_TOO_SMALL
)
{
low_free
(
_size
,
(
unsigned
long
)
mem_map
);
goto
again
;
}
if
(
status
!=
EFI_SUCCESS
)
if
(
status
!=
EFI_SUCCESS
)
goto
free_mem_map
;
return
status
;
memcpy
(
&
efi
->
efi_loader_signature
,
EFI_LOADER_SIGNATURE
,
sizeof
(
__u32
));
memcpy
(
&
efi
->
efi_loader_signature
,
EFI_LOADER_SIGNATURE
,
sizeof
(
__u32
));
efi
->
efi_systab
=
(
unsigned
long
)
sys_table
;
efi
->
efi_systab
=
(
unsigned
long
)
sys_table
;
...
@@ -1043,6 +567,7 @@ static efi_status_t exit_boot(struct boot_params *boot_params,
...
@@ -1043,6 +567,7 @@ static efi_status_t exit_boot(struct boot_params *boot_params,
goto
free_mem_map
;
goto
free_mem_map
;
called_exit
=
true
;
called_exit
=
true
;
efi_call_phys1
(
sys_table
->
boottime
->
free_pool
,
mem_map
);
goto
get_map
;
goto
get_map
;
}
}
...
@@ -1111,44 +636,10 @@ static efi_status_t exit_boot(struct boot_params *boot_params,
...
@@ -1111,44 +636,10 @@ static efi_status_t exit_boot(struct boot_params *boot_params,
return
EFI_SUCCESS
;
return
EFI_SUCCESS
;
free_mem_map:
free_mem_map:
low_free
(
_size
,
(
unsigned
long
)
mem_map
);
efi_call_phys1
(
sys_table
->
boottime
->
free_pool
,
mem_map
);
return
status
;
return
status
;
}
}
static
efi_status_t
relocate_kernel
(
struct
setup_header
*
hdr
)
{
unsigned
long
start
,
nr_pages
;
efi_status_t
status
;
/*
* The EFI firmware loader could have placed the kernel image
* anywhere in memory, but the kernel has various restrictions
* on the max physical address it can run at. Attempt to move
* the kernel to boot_params.pref_address, or as low as
* possible.
*/
start
=
hdr
->
pref_address
;
nr_pages
=
round_up
(
hdr
->
init_size
,
EFI_PAGE_SIZE
)
/
EFI_PAGE_SIZE
;
status
=
efi_call_phys4
(
sys_table
->
boottime
->
allocate_pages
,
EFI_ALLOCATE_ADDRESS
,
EFI_LOADER_DATA
,
nr_pages
,
&
start
);
if
(
status
!=
EFI_SUCCESS
)
{
status
=
low_alloc
(
hdr
->
init_size
,
hdr
->
kernel_alignment
,
&
start
);
if
(
status
!=
EFI_SUCCESS
)
efi_printk
(
"Failed to alloc mem for kernel
\n
"
);
}
if
(
status
==
EFI_SUCCESS
)
memcpy
((
void
*
)
start
,
(
void
*
)(
unsigned
long
)
hdr
->
code32_start
,
hdr
->
init_size
);
hdr
->
pref_address
=
hdr
->
code32_start
;
hdr
->
code32_start
=
(
__u32
)
start
;
return
status
;
}
/*
/*
* On success we return a pointer to a boot_params structure, and NULL
* On success we return a pointer to a boot_params structure, and NULL
...
@@ -1177,14 +668,15 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
...
@@ -1177,14 +668,15 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
EFI_LOADER_DATA
,
sizeof
(
*
gdt
),
EFI_LOADER_DATA
,
sizeof
(
*
gdt
),
(
void
**
)
&
gdt
);
(
void
**
)
&
gdt
);
if
(
status
!=
EFI_SUCCESS
)
{
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
"Failed to alloc mem for gdt structure
\n
"
);
efi_printk
(
sys_table
,
"Failed to alloc mem for gdt structure
\n
"
);
goto
fail
;
goto
fail
;
}
}
gdt
->
size
=
0x800
;
gdt
->
size
=
0x800
;
status
=
low_alloc
(
gdt
->
size
,
8
,
(
unsigned
long
*
)
&
gdt
->
address
);
status
=
efi_low_alloc
(
sys_table
,
gdt
->
size
,
8
,
(
unsigned
long
*
)
&
gdt
->
address
);
if
(
status
!=
EFI_SUCCESS
)
{
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
"Failed to alloc mem for gdt
\n
"
);
efi_printk
(
sys_table
,
"Failed to alloc mem for gdt
\n
"
);
goto
fail
;
goto
fail
;
}
}
...
@@ -1192,7 +684,7 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
...
@@ -1192,7 +684,7 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
EFI_LOADER_DATA
,
sizeof
(
*
idt
),
EFI_LOADER_DATA
,
sizeof
(
*
idt
),
(
void
**
)
&
idt
);
(
void
**
)
&
idt
);
if
(
status
!=
EFI_SUCCESS
)
{
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
"Failed to alloc mem for idt structure
\n
"
);
efi_printk
(
sys_table
,
"Failed to alloc mem for idt structure
\n
"
);
goto
fail
;
goto
fail
;
}
}
...
@@ -1204,10 +696,16 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
...
@@ -1204,10 +696,16 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
* address, relocate it.
* address, relocate it.
*/
*/
if
(
hdr
->
pref_address
!=
hdr
->
code32_start
)
{
if
(
hdr
->
pref_address
!=
hdr
->
code32_start
)
{
status
=
relocate_kernel
(
hdr
);
unsigned
long
bzimage_addr
=
hdr
->
code32_start
;
status
=
efi_relocate_kernel
(
sys_table
,
&
bzimage_addr
,
hdr
->
init_size
,
hdr
->
init_size
,
hdr
->
pref_address
,
hdr
->
kernel_alignment
);
if
(
status
!=
EFI_SUCCESS
)
if
(
status
!=
EFI_SUCCESS
)
goto
fail
;
goto
fail
;
hdr
->
pref_address
=
hdr
->
code32_start
;
hdr
->
code32_start
=
bzimage_addr
;
}
}
status
=
exit_boot
(
boot_params
,
handle
);
status
=
exit_boot
(
boot_params
,
handle
);
...
...
arch/x86/boot/compressed/eboot.h
浏览文件 @
3203209d
...
@@ -11,9 +11,6 @@
...
@@ -11,9 +11,6 @@
#define DESC_TYPE_CODE_DATA (1 << 0)
#define DESC_TYPE_CODE_DATA (1 << 0)
#define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT)
#define EFI_READ_CHUNK_SIZE (1024 * 1024)
#define EFI_CONSOLE_OUT_DEVICE_GUID \
#define EFI_CONSOLE_OUT_DEVICE_GUID \
EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, \
EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, \
0x3f, 0xc1, 0x4d)
0x3f, 0xc1, 0x4d)
...
@@ -62,10 +59,4 @@ struct efi_uga_draw_protocol {
...
@@ -62,10 +59,4 @@ struct efi_uga_draw_protocol {
void
*
blt
;
void
*
blt
;
};
};
struct
efi_simple_text_output_protocol
{
void
*
reset
;
void
*
output_string
;
void
*
test_string
;
};
#endif
/* BOOT_COMPRESSED_EBOOT_H */
#endif
/* BOOT_COMPRESSED_EBOOT_H */
drivers/firmware/efi/efi-stub-helper.c
0 → 100644
浏览文件 @
3203209d
/*
* Helper functions used by the EFI stub on multiple
* architectures. This should be #included by the EFI stub
* implementation files.
*
* Copyright 2011 Intel Corporation; author Matt Fleming
*
* This file is part of the Linux kernel, and is made available
* under the terms of the GNU General Public License version 2.
*
*/
#define EFI_READ_CHUNK_SIZE (1024 * 1024)
struct
file_info
{
efi_file_handle_t
*
handle
;
u64
size
;
};
static
void
efi_char16_printk
(
efi_system_table_t
*
sys_table_arg
,
efi_char16_t
*
str
)
{
struct
efi_simple_text_output_protocol
*
out
;
out
=
(
struct
efi_simple_text_output_protocol
*
)
sys_table_arg
->
con_out
;
efi_call_phys2
(
out
->
output_string
,
out
,
str
);
}
static
void
efi_printk
(
efi_system_table_t
*
sys_table_arg
,
char
*
str
)
{
char
*
s8
;
for
(
s8
=
str
;
*
s8
;
s8
++
)
{
efi_char16_t
ch
[
2
]
=
{
0
};
ch
[
0
]
=
*
s8
;
if
(
*
s8
==
'\n'
)
{
efi_char16_t
nl
[
2
]
=
{
'\r'
,
0
};
efi_char16_printk
(
sys_table_arg
,
nl
);
}
efi_char16_printk
(
sys_table_arg
,
ch
);
}
}
static
efi_status_t
efi_get_memory_map
(
efi_system_table_t
*
sys_table_arg
,
efi_memory_desc_t
**
map
,
unsigned
long
*
map_size
,
unsigned
long
*
desc_size
,
u32
*
desc_ver
,
unsigned
long
*
key_ptr
)
{
efi_memory_desc_t
*
m
=
NULL
;
efi_status_t
status
;
unsigned
long
key
;
u32
desc_version
;
*
map_size
=
sizeof
(
*
m
)
*
32
;
again:
/*
* Add an additional efi_memory_desc_t because we're doing an
* allocation which may be in a new descriptor region.
*/
*
map_size
+=
sizeof
(
*
m
);
status
=
efi_call_phys3
(
sys_table_arg
->
boottime
->
allocate_pool
,
EFI_LOADER_DATA
,
*
map_size
,
(
void
**
)
&
m
);
if
(
status
!=
EFI_SUCCESS
)
goto
fail
;
status
=
efi_call_phys5
(
sys_table_arg
->
boottime
->
get_memory_map
,
map_size
,
m
,
&
key
,
desc_size
,
&
desc_version
);
if
(
status
==
EFI_BUFFER_TOO_SMALL
)
{
efi_call_phys1
(
sys_table_arg
->
boottime
->
free_pool
,
m
);
goto
again
;
}
if
(
status
!=
EFI_SUCCESS
)
efi_call_phys1
(
sys_table_arg
->
boottime
->
free_pool
,
m
);
if
(
key_ptr
&&
status
==
EFI_SUCCESS
)
*
key_ptr
=
key
;
if
(
desc_ver
&&
status
==
EFI_SUCCESS
)
*
desc_ver
=
desc_version
;
fail:
*
map
=
m
;
return
status
;
}
/*
* Allocate at the highest possible address that is not above 'max'.
*/
static
efi_status_t
efi_high_alloc
(
efi_system_table_t
*
sys_table_arg
,
unsigned
long
size
,
unsigned
long
align
,
unsigned
long
*
addr
,
unsigned
long
max
)
{
unsigned
long
map_size
,
desc_size
;
efi_memory_desc_t
*
map
;
efi_status_t
status
;
unsigned
long
nr_pages
;
u64
max_addr
=
0
;
int
i
;
status
=
efi_get_memory_map
(
sys_table_arg
,
&
map
,
&
map_size
,
&
desc_size
,
NULL
,
NULL
);
if
(
status
!=
EFI_SUCCESS
)
goto
fail
;
/*
* Enforce minimum alignment that EFI requires when requesting
* a specific address. We are doing page-based allocations,
* so we must be aligned to a page.
*/
if
(
align
<
EFI_PAGE_SIZE
)
align
=
EFI_PAGE_SIZE
;
nr_pages
=
round_up
(
size
,
EFI_PAGE_SIZE
)
/
EFI_PAGE_SIZE
;
again:
for
(
i
=
0
;
i
<
map_size
/
desc_size
;
i
++
)
{
efi_memory_desc_t
*
desc
;
unsigned
long
m
=
(
unsigned
long
)
map
;
u64
start
,
end
;
desc
=
(
efi_memory_desc_t
*
)(
m
+
(
i
*
desc_size
));
if
(
desc
->
type
!=
EFI_CONVENTIONAL_MEMORY
)
continue
;
if
(
desc
->
num_pages
<
nr_pages
)
continue
;
start
=
desc
->
phys_addr
;
end
=
start
+
desc
->
num_pages
*
(
1UL
<<
EFI_PAGE_SHIFT
);
if
((
start
+
size
)
>
end
||
(
start
+
size
)
>
max
)
continue
;
if
(
end
-
size
>
max
)
end
=
max
;
if
(
round_down
(
end
-
size
,
align
)
<
start
)
continue
;
start
=
round_down
(
end
-
size
,
align
);
/*
* Don't allocate at 0x0. It will confuse code that
* checks pointers against NULL.
*/
if
(
start
==
0x0
)
continue
;
if
(
start
>
max_addr
)
max_addr
=
start
;
}
if
(
!
max_addr
)
status
=
EFI_NOT_FOUND
;
else
{
status
=
efi_call_phys4
(
sys_table_arg
->
boottime
->
allocate_pages
,
EFI_ALLOCATE_ADDRESS
,
EFI_LOADER_DATA
,
nr_pages
,
&
max_addr
);
if
(
status
!=
EFI_SUCCESS
)
{
max
=
max_addr
;
max_addr
=
0
;
goto
again
;
}
*
addr
=
max_addr
;
}
efi_call_phys1
(
sys_table_arg
->
boottime
->
free_pool
,
map
);
fail:
return
status
;
}
/*
* Allocate at the lowest possible address.
*/
static
efi_status_t
efi_low_alloc
(
efi_system_table_t
*
sys_table_arg
,
unsigned
long
size
,
unsigned
long
align
,
unsigned
long
*
addr
)
{
unsigned
long
map_size
,
desc_size
;
efi_memory_desc_t
*
map
;
efi_status_t
status
;
unsigned
long
nr_pages
;
int
i
;
status
=
efi_get_memory_map
(
sys_table_arg
,
&
map
,
&
map_size
,
&
desc_size
,
NULL
,
NULL
);
if
(
status
!=
EFI_SUCCESS
)
goto
fail
;
/*
* Enforce minimum alignment that EFI requires when requesting
* a specific address. We are doing page-based allocations,
* so we must be aligned to a page.
*/
if
(
align
<
EFI_PAGE_SIZE
)
align
=
EFI_PAGE_SIZE
;
nr_pages
=
round_up
(
size
,
EFI_PAGE_SIZE
)
/
EFI_PAGE_SIZE
;
for
(
i
=
0
;
i
<
map_size
/
desc_size
;
i
++
)
{
efi_memory_desc_t
*
desc
;
unsigned
long
m
=
(
unsigned
long
)
map
;
u64
start
,
end
;
desc
=
(
efi_memory_desc_t
*
)(
m
+
(
i
*
desc_size
));
if
(
desc
->
type
!=
EFI_CONVENTIONAL_MEMORY
)
continue
;
if
(
desc
->
num_pages
<
nr_pages
)
continue
;
start
=
desc
->
phys_addr
;
end
=
start
+
desc
->
num_pages
*
(
1UL
<<
EFI_PAGE_SHIFT
);
/*
* Don't allocate at 0x0. It will confuse code that
* checks pointers against NULL. Skip the first 8
* bytes so we start at a nice even number.
*/
if
(
start
==
0x0
)
start
+=
8
;
start
=
round_up
(
start
,
align
);
if
((
start
+
size
)
>
end
)
continue
;
status
=
efi_call_phys4
(
sys_table_arg
->
boottime
->
allocate_pages
,
EFI_ALLOCATE_ADDRESS
,
EFI_LOADER_DATA
,
nr_pages
,
&
start
);
if
(
status
==
EFI_SUCCESS
)
{
*
addr
=
start
;
break
;
}
}
if
(
i
==
map_size
/
desc_size
)
status
=
EFI_NOT_FOUND
;
efi_call_phys1
(
sys_table_arg
->
boottime
->
free_pool
,
map
);
fail:
return
status
;
}
static
void
efi_free
(
efi_system_table_t
*
sys_table_arg
,
unsigned
long
size
,
unsigned
long
addr
)
{
unsigned
long
nr_pages
;
if
(
!
size
)
return
;
nr_pages
=
round_up
(
size
,
EFI_PAGE_SIZE
)
/
EFI_PAGE_SIZE
;
efi_call_phys2
(
sys_table_arg
->
boottime
->
free_pages
,
addr
,
nr_pages
);
}
/*
* Check the cmdline for a LILO-style file= arguments.
*
* We only support loading a file from the same filesystem as
* the kernel image.
*/
static
efi_status_t
handle_cmdline_files
(
efi_system_table_t
*
sys_table_arg
,
efi_loaded_image_t
*
image
,
char
*
cmd_line
,
char
*
option_string
,
unsigned
long
max_addr
,
unsigned
long
*
load_addr
,
unsigned
long
*
load_size
)
{
struct
file_info
*
files
;
unsigned
long
file_addr
;
efi_guid_t
fs_proto
=
EFI_FILE_SYSTEM_GUID
;
u64
file_size_total
;
efi_file_io_interface_t
*
io
;
efi_file_handle_t
*
fh
;
efi_status_t
status
;
int
nr_files
;
char
*
str
;
int
i
,
j
,
k
;
file_addr
=
0
;
file_size_total
=
0
;
str
=
cmd_line
;
j
=
0
;
/* See close_handles */
if
(
!
load_addr
||
!
load_size
)
return
EFI_INVALID_PARAMETER
;
*
load_addr
=
0
;
*
load_size
=
0
;
if
(
!
str
||
!*
str
)
return
EFI_SUCCESS
;
for
(
nr_files
=
0
;
*
str
;
nr_files
++
)
{
str
=
strstr
(
str
,
option_string
);
if
(
!
str
)
break
;
str
+=
strlen
(
option_string
);
/* Skip any leading slashes */
while
(
*
str
==
'/'
||
*
str
==
'\\'
)
str
++
;
while
(
*
str
&&
*
str
!=
' '
&&
*
str
!=
'\n'
)
str
++
;
}
if
(
!
nr_files
)
return
EFI_SUCCESS
;
status
=
efi_call_phys3
(
sys_table_arg
->
boottime
->
allocate_pool
,
EFI_LOADER_DATA
,
nr_files
*
sizeof
(
*
files
),
(
void
**
)
&
files
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
sys_table_arg
,
"Failed to alloc mem for file handle list
\n
"
);
goto
fail
;
}
str
=
cmd_line
;
for
(
i
=
0
;
i
<
nr_files
;
i
++
)
{
struct
file_info
*
file
;
efi_file_handle_t
*
h
;
efi_file_info_t
*
info
;
efi_char16_t
filename_16
[
256
];
unsigned
long
info_sz
;
efi_guid_t
info_guid
=
EFI_FILE_INFO_ID
;
efi_char16_t
*
p
;
u64
file_sz
;
str
=
strstr
(
str
,
option_string
);
if
(
!
str
)
break
;
str
+=
strlen
(
option_string
);
file
=
&
files
[
i
];
p
=
filename_16
;
/* Skip any leading slashes */
while
(
*
str
==
'/'
||
*
str
==
'\\'
)
str
++
;
while
(
*
str
&&
*
str
!=
' '
&&
*
str
!=
'\n'
)
{
if
((
u8
*
)
p
>=
(
u8
*
)
filename_16
+
sizeof
(
filename_16
))
break
;
if
(
*
str
==
'/'
)
{
*
p
++
=
'\\'
;
str
++
;
}
else
{
*
p
++
=
*
str
++
;
}
}
*
p
=
'\0'
;
/* Only open the volume once. */
if
(
!
i
)
{
efi_boot_services_t
*
boottime
;
boottime
=
sys_table_arg
->
boottime
;
status
=
efi_call_phys3
(
boottime
->
handle_protocol
,
image
->
device_handle
,
&
fs_proto
,
(
void
**
)
&
io
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
sys_table_arg
,
"Failed to handle fs_proto
\n
"
);
goto
free_files
;
}
status
=
efi_call_phys2
(
io
->
open_volume
,
io
,
&
fh
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
sys_table_arg
,
"Failed to open volume
\n
"
);
goto
free_files
;
}
}
status
=
efi_call_phys5
(
fh
->
open
,
fh
,
&
h
,
filename_16
,
EFI_FILE_MODE_READ
,
(
u64
)
0
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
sys_table_arg
,
"Failed to open file: "
);
efi_char16_printk
(
sys_table_arg
,
filename_16
);
efi_printk
(
sys_table_arg
,
"
\n
"
);
goto
close_handles
;
}
file
->
handle
=
h
;
info_sz
=
0
;
status
=
efi_call_phys4
(
h
->
get_info
,
h
,
&
info_guid
,
&
info_sz
,
NULL
);
if
(
status
!=
EFI_BUFFER_TOO_SMALL
)
{
efi_printk
(
sys_table_arg
,
"Failed to get file info size
\n
"
);
goto
close_handles
;
}
grow:
status
=
efi_call_phys3
(
sys_table_arg
->
boottime
->
allocate_pool
,
EFI_LOADER_DATA
,
info_sz
,
(
void
**
)
&
info
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
sys_table_arg
,
"Failed to alloc mem for file info
\n
"
);
goto
close_handles
;
}
status
=
efi_call_phys4
(
h
->
get_info
,
h
,
&
info_guid
,
&
info_sz
,
info
);
if
(
status
==
EFI_BUFFER_TOO_SMALL
)
{
efi_call_phys1
(
sys_table_arg
->
boottime
->
free_pool
,
info
);
goto
grow
;
}
file_sz
=
info
->
file_size
;
efi_call_phys1
(
sys_table_arg
->
boottime
->
free_pool
,
info
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
sys_table_arg
,
"Failed to get file info
\n
"
);
goto
close_handles
;
}
file
->
size
=
file_sz
;
file_size_total
+=
file_sz
;
}
if
(
file_size_total
)
{
unsigned
long
addr
;
/*
* Multiple files need to be at consecutive addresses in memory,
* so allocate enough memory for all the files. This is used
* for loading multiple files.
*/
status
=
efi_high_alloc
(
sys_table_arg
,
file_size_total
,
0x1000
,
&
file_addr
,
max_addr
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
sys_table_arg
,
"Failed to alloc highmem for files
\n
"
);
goto
close_handles
;
}
/* We've run out of free low memory. */
if
(
file_addr
>
max_addr
)
{
efi_printk
(
sys_table_arg
,
"We've run out of free low memory
\n
"
);
status
=
EFI_INVALID_PARAMETER
;
goto
free_file_total
;
}
addr
=
file_addr
;
for
(
j
=
0
;
j
<
nr_files
;
j
++
)
{
unsigned
long
size
;
size
=
files
[
j
].
size
;
while
(
size
)
{
unsigned
long
chunksize
;
if
(
size
>
EFI_READ_CHUNK_SIZE
)
chunksize
=
EFI_READ_CHUNK_SIZE
;
else
chunksize
=
size
;
status
=
efi_call_phys3
(
fh
->
read
,
files
[
j
].
handle
,
&
chunksize
,
(
void
*
)
addr
);
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
sys_table_arg
,
"Failed to read file
\n
"
);
goto
free_file_total
;
}
addr
+=
chunksize
;
size
-=
chunksize
;
}
efi_call_phys1
(
fh
->
close
,
files
[
j
].
handle
);
}
}
efi_call_phys1
(
sys_table_arg
->
boottime
->
free_pool
,
files
);
*
load_addr
=
file_addr
;
*
load_size
=
file_size_total
;
return
status
;
free_file_total:
efi_free
(
sys_table_arg
,
file_size_total
,
file_addr
);
close_handles:
for
(
k
=
j
;
k
<
i
;
k
++
)
efi_call_phys1
(
fh
->
close
,
files
[
k
].
handle
);
free_files:
efi_call_phys1
(
sys_table_arg
->
boottime
->
free_pool
,
files
);
fail:
*
load_addr
=
0
;
*
load_size
=
0
;
return
status
;
}
/*
* Relocate a kernel image, either compressed or uncompressed.
* In the ARM64 case, all kernel images are currently
* uncompressed, and as such when we relocate it we need to
* allocate additional space for the BSS segment. Any low
* memory that this function should avoid needs to be
* unavailable in the EFI memory map, as if the preferred
* address is not available the lowest available address will
* be used.
*/
static
efi_status_t
efi_relocate_kernel
(
efi_system_table_t
*
sys_table_arg
,
unsigned
long
*
image_addr
,
unsigned
long
image_size
,
unsigned
long
alloc_size
,
unsigned
long
preferred_addr
,
unsigned
long
alignment
)
{
unsigned
long
cur_image_addr
;
unsigned
long
new_addr
=
0
;
efi_status_t
status
;
unsigned
long
nr_pages
;
efi_physical_addr_t
efi_addr
=
preferred_addr
;
if
(
!
image_addr
||
!
image_size
||
!
alloc_size
)
return
EFI_INVALID_PARAMETER
;
if
(
alloc_size
<
image_size
)
return
EFI_INVALID_PARAMETER
;
cur_image_addr
=
*
image_addr
;
/*
* The EFI firmware loader could have placed the kernel image
* anywhere in memory, but the kernel has restrictions on the
* max physical address it can run at. Some architectures
* also have a prefered address, so first try to relocate
* to the preferred address. If that fails, allocate as low
* as possible while respecting the required alignment.
*/
nr_pages
=
round_up
(
alloc_size
,
EFI_PAGE_SIZE
)
/
EFI_PAGE_SIZE
;
status
=
efi_call_phys4
(
sys_table_arg
->
boottime
->
allocate_pages
,
EFI_ALLOCATE_ADDRESS
,
EFI_LOADER_DATA
,
nr_pages
,
&
efi_addr
);
new_addr
=
efi_addr
;
/*
* If preferred address allocation failed allocate as low as
* possible.
*/
if
(
status
!=
EFI_SUCCESS
)
{
status
=
efi_low_alloc
(
sys_table_arg
,
alloc_size
,
alignment
,
&
new_addr
);
}
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
sys_table_arg
,
"ERROR: Failed to allocate usable memory for kernel.
\n
"
);
return
status
;
}
/*
* We know source/dest won't overlap since both memory ranges
* have been allocated by UEFI, so we can safely use memcpy.
*/
memcpy
((
void
*
)
new_addr
,
(
void
*
)
cur_image_addr
,
image_size
);
/* Zero any extra space we may have allocated for BSS. */
memset
((
void
*
)(
new_addr
+
image_size
),
alloc_size
-
image_size
,
0
);
/* Return the new address of the relocated image. */
*
image_addr
=
new_addr
;
return
status
;
}
/*
* Convert the unicode UEFI command line to ASCII to pass to kernel.
* Size of memory allocated return in *cmd_line_len.
* Returns NULL on error.
*/
static
char
*
efi_convert_cmdline_to_ascii
(
efi_system_table_t
*
sys_table_arg
,
efi_loaded_image_t
*
image
,
int
*
cmd_line_len
)
{
u16
*
s2
;
u8
*
s1
=
NULL
;
unsigned
long
cmdline_addr
=
0
;
int
load_options_size
=
image
->
load_options_size
/
2
;
/* ASCII */
void
*
options
=
image
->
load_options
;
int
options_size
=
0
;
efi_status_t
status
;
int
i
;
u16
zero
=
0
;
if
(
options
)
{
s2
=
options
;
while
(
*
s2
&&
*
s2
!=
'\n'
&&
options_size
<
load_options_size
)
{
s2
++
;
options_size
++
;
}
}
if
(
options_size
==
0
)
{
/* No command line options, so return empty string*/
options_size
=
1
;
options
=
&
zero
;
}
options_size
++
;
/* NUL termination */
#ifdef CONFIG_ARM
/*
* For ARM, allocate at a high address to avoid reserved
* regions at low addresses that we don't know the specfics of
* at the time we are processing the command line.
*/
status
=
efi_high_alloc
(
sys_table_arg
,
options_size
,
0
,
&
cmdline_addr
,
0xfffff000
);
#else
status
=
efi_low_alloc
(
sys_table_arg
,
options_size
,
0
,
&
cmdline_addr
);
#endif
if
(
status
!=
EFI_SUCCESS
)
return
NULL
;
s1
=
(
u8
*
)
cmdline_addr
;
s2
=
(
u16
*
)
options
;
for
(
i
=
0
;
i
<
options_size
-
1
;
i
++
)
*
s1
++
=
*
s2
++
;
*
s1
=
'\0'
;
*
cmd_line_len
=
options_size
;
return
(
char
*
)
cmdline_addr
;
}
include/linux/efi.h
浏览文件 @
3203209d
...
@@ -39,6 +39,8 @@
...
@@ -39,6 +39,8 @@
typedef
unsigned
long
efi_status_t
;
typedef
unsigned
long
efi_status_t
;
typedef
u8
efi_bool_t
;
typedef
u8
efi_bool_t
;
typedef
u16
efi_char16_t
;
/* UNICODE character */
typedef
u16
efi_char16_t
;
/* UNICODE character */
typedef
u64
efi_physical_addr_t
;
typedef
void
*
efi_handle_t
;
typedef
struct
{
typedef
struct
{
...
@@ -96,6 +98,7 @@ typedef struct {
...
@@ -96,6 +98,7 @@ typedef struct {
#define EFI_MEMORY_DESCRIPTOR_VERSION 1
#define EFI_MEMORY_DESCRIPTOR_VERSION 1
#define EFI_PAGE_SHIFT 12
#define EFI_PAGE_SHIFT 12
#define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT)
typedef
struct
{
typedef
struct
{
u32
type
;
u32
type
;
...
@@ -157,11 +160,13 @@ typedef struct {
...
@@ -157,11 +160,13 @@ typedef struct {
efi_table_hdr_t
hdr
;
efi_table_hdr_t
hdr
;
void
*
raise_tpl
;
void
*
raise_tpl
;
void
*
restore_tpl
;
void
*
restore_tpl
;
void
*
allocate_pages
;
efi_status_t
(
*
allocate_pages
)(
int
,
int
,
unsigned
long
,
void
*
free_pages
;
efi_physical_addr_t
*
);
void
*
get_memory_map
;
efi_status_t
(
*
free_pages
)(
efi_physical_addr_t
,
unsigned
long
);
void
*
allocate_pool
;
efi_status_t
(
*
get_memory_map
)(
unsigned
long
*
,
void
*
,
unsigned
long
*
,
void
*
free_pool
;
unsigned
long
*
,
u32
*
);
efi_status_t
(
*
allocate_pool
)(
int
,
unsigned
long
,
void
**
);
efi_status_t
(
*
free_pool
)(
void
*
);
void
*
create_event
;
void
*
create_event
;
void
*
set_timer
;
void
*
set_timer
;
void
*
wait_for_event
;
void
*
wait_for_event
;
...
@@ -171,7 +176,7 @@ typedef struct {
...
@@ -171,7 +176,7 @@ typedef struct {
void
*
install_protocol_interface
;
void
*
install_protocol_interface
;
void
*
reinstall_protocol_interface
;
void
*
reinstall_protocol_interface
;
void
*
uninstall_protocol_interface
;
void
*
uninstall_protocol_interface
;
void
*
handle_protocol
;
efi_status_t
(
*
handle_protocol
)(
efi_handle_t
,
efi_guid_t
*
,
void
**
)
;
void
*
__reserved
;
void
*
__reserved
;
void
*
register_protocol_notify
;
void
*
register_protocol_notify
;
void
*
locate_handle
;
void
*
locate_handle
;
...
@@ -181,7 +186,7 @@ typedef struct {
...
@@ -181,7 +186,7 @@ typedef struct {
void
*
start_image
;
void
*
start_image
;
void
*
exit
;
void
*
exit
;
void
*
unload_image
;
void
*
unload_image
;
void
*
exit_boot_services
;
efi_status_t
(
*
exit_boot_services
)(
efi_handle_t
,
unsigned
long
)
;
void
*
get_next_monotonic_count
;
void
*
get_next_monotonic_count
;
void
*
stall
;
void
*
stall
;
void
*
set_watchdog_timer
;
void
*
set_watchdog_timer
;
...
@@ -494,10 +499,6 @@ typedef struct {
...
@@ -494,10 +499,6 @@ typedef struct {
unsigned
long
unload
;
unsigned
long
unload
;
}
efi_loaded_image_t
;
}
efi_loaded_image_t
;
typedef
struct
{
u64
revision
;
void
*
open_volume
;
}
efi_file_io_interface_t
;
typedef
struct
{
typedef
struct
{
u64
size
;
u64
size
;
...
@@ -510,20 +511,30 @@ typedef struct {
...
@@ -510,20 +511,30 @@ typedef struct {
efi_char16_t
filename
[
1
];
efi_char16_t
filename
[
1
];
}
efi_file_info_t
;
}
efi_file_info_t
;
typedef
struct
{
typedef
struct
_efi_file_handle
{
u64
revision
;
u64
revision
;
void
*
open
;
efi_status_t
(
*
open
)(
struct
_efi_file_handle
*
,
void
*
close
;
struct
_efi_file_handle
**
,
efi_char16_t
*
,
u64
,
u64
);
efi_status_t
(
*
close
)(
struct
_efi_file_handle
*
);
void
*
delete
;
void
*
delete
;
void
*
read
;
efi_status_t
(
*
read
)(
struct
_efi_file_handle
*
,
unsigned
long
*
,
void
*
);
void
*
write
;
void
*
write
;
void
*
get_position
;
void
*
get_position
;
void
*
set_position
;
void
*
set_position
;
void
*
get_info
;
efi_status_t
(
*
get_info
)(
struct
_efi_file_handle
*
,
efi_guid_t
*
,
unsigned
long
*
,
void
*
);
void
*
set_info
;
void
*
set_info
;
void
*
flush
;
void
*
flush
;
}
efi_file_handle_t
;
}
efi_file_handle_t
;
typedef
struct
_efi_file_io_interface
{
u64
revision
;
int
(
*
open_volume
)(
struct
_efi_file_io_interface
*
,
efi_file_handle_t
**
);
}
efi_file_io_interface_t
;
#define EFI_FILE_MODE_READ 0x0000000000000001
#define EFI_FILE_MODE_READ 0x0000000000000001
#define EFI_FILE_MODE_WRITE 0x0000000000000002
#define EFI_FILE_MODE_WRITE 0x0000000000000002
#define EFI_FILE_MODE_CREATE 0x8000000000000000
#define EFI_FILE_MODE_CREATE 0x8000000000000000
...
@@ -792,6 +803,13 @@ struct efivar_entry {
...
@@ -792,6 +803,13 @@ struct efivar_entry {
struct
kobject
kobj
;
struct
kobject
kobj
;
};
};
struct
efi_simple_text_output_protocol
{
void
*
reset
;
efi_status_t
(
*
output_string
)(
void
*
,
void
*
);
void
*
test_string
;
};
extern
struct
list_head
efivar_sysfs_list
;
extern
struct
list_head
efivar_sysfs_list
;
static
inline
void
static
inline
void
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录