Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
3203209d
Commit
3203209d
authored
Sep 25, 2013
by
Matt Fleming
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'arm/common' into next
parents
9efff389
4e283088
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
712 additions
and
567 deletions
+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
No files found.
Documentation/
x86/
efi-stub.txt
→
Documentation/efi-stub.txt
View file @
3203209d
File moved
arch/x86/Kconfig
View file @
3203209d
...
...
@@ -1579,7 +1579,7 @@ config EFI_STUB
This kernel feature allows a bzImage to be loaded directly
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
def_bool y
...
...
arch/x86/boot/compressed/eboot.c
View file @
3203209d
...
...
@@ -19,214 +19,10 @@
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
,
EFI_ALLOCATE_ADDRESS
,
EFI_LOADER_DATA
,
nr_pages
,
&
start
);
if
(
status
==
EFI_SUCCESS
)
{
*
addr
=
start
;
break
;
}
}
#include "../../../../drivers/firmware/efi/efi-stub-helper.c"
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
)
{
...
...
@@ -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
...
...
@@ -875,14 +435,15 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
struct
efi_info
*
efi
;
efi_loaded_image_t
*
image
;
void
*
options
;
u32
load_options_size
;
efi_guid_t
proto
=
LOADED_IMAGE_PROTOCOL_GUID
;
int
options_size
=
0
;
efi_status_t
status
;
unsigned
long
cmdline
;
char
*
cmdline_ptr
;
u16
*
s2
;
u8
*
s1
;
int
i
;
unsigned
long
ramdisk_addr
;
unsigned
long
ramdisk_size
;
sys_table
=
_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
,
handle
,
&
proto
,
(
void
*
)
&
image
);
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
;
}
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
)
{
efi_printk
(
"Failed to alloc lowmem for boot params
\n
"
);
efi_printk
(
sys_table
,
"Failed to alloc lowmem for boot params
\n
"
);
return
NULL
;
}
...
...
@@ -926,40 +488,11 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
hdr
->
type_of_loader
=
0x21
;
/* Convert unicode cmdline to ascii */
options
=
image
->
load_options
;
load_options_size
=
image
->
load_options_size
/
2
;
/* ASCII */
cmdline
=
0
;
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
"
);
cmdline_ptr
=
efi_convert_cmdline_to_ascii
(
sys_table
,
image
,
&
options_size
);
if
(
!
cmdline_ptr
)
goto
fail
;
}
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
->
cmd_line_ptr
=
(
unsigned
long
)
cmdline_ptr
;
hdr
->
ramdisk_image
=
0
;
hdr
->
ramdisk_size
=
0
;
...
...
@@ -969,16 +502,20 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table)
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
)
goto
fail2
;
hdr
->
ramdisk_image
=
ramdisk_addr
;
hdr
->
ramdisk_size
=
ramdisk_size
;
return
boot_params
;
fail2:
if
(
options_size
)
low_free
(
options_size
,
hdr
->
cmd_line_ptr
);
efi_free
(
sys_table
,
options_size
,
hdr
->
cmd_line_ptr
);
fail:
low_free
(
0x4000
,
(
unsigned
long
)
boot_params
);
efi_free
(
sys_table
,
0x4000
,
(
unsigned
long
)
boot_params
);
return
NULL
;
}
...
...
@@ -996,25 +533,12 @@ static efi_status_t exit_boot(struct boot_params *boot_params,
u8
nr_entries
;
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:
status
=
efi_call_phys5
(
sys_table
->
boottime
->
get_memory_map
,
&
size
,
mem_map
,
&
key
,
&
desc_size
,
&
desc_version
);
if
(
status
==
EFI_BUFFER_TOO_SMALL
)
{
low_free
(
_size
,
(
unsigned
long
)
mem_map
);
goto
again
;
}
status
=
efi_get_memory_map
(
sys_table
,
&
mem_map
,
&
size
,
&
desc_size
,
&
desc_version
,
&
key
);
if
(
status
!=
EFI_SUCCESS
)
goto
free_mem_map
;
return
status
;
memcpy
(
&
efi
->
efi_loader_signature
,
EFI_LOADER_SIGNATURE
,
sizeof
(
__u32
));
efi
->
efi_systab
=
(
unsigned
long
)
sys_table
;
...
...
@@ -1043,6 +567,7 @@ static efi_status_t exit_boot(struct boot_params *boot_params,
goto
free_mem_map
;
called_exit
=
true
;
efi_call_phys1
(
sys_table
->
boottime
->
free_pool
,
mem_map
);
goto
get_map
;
}
...
...
@@ -1111,44 +636,10 @@ static efi_status_t exit_boot(struct boot_params *boot_params,
return
EFI_SUCCESS
;
free_mem_map:
low_free
(
_size
,
(
unsigned
long
)
mem_map
);
efi_call_phys1
(
sys_table
->
boottime
->
free_pool
,
mem_map
);
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
...
...
@@ -1177,14 +668,15 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
EFI_LOADER_DATA
,
sizeof
(
*
gdt
),
(
void
**
)
&
gdt
);
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
;
}
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
)
{
efi_printk
(
"Failed to alloc mem for gdt
\n
"
);
efi_printk
(
sys_table
,
"Failed to alloc mem for gdt
\n
"
);
goto
fail
;
}
...
...
@@ -1192,7 +684,7 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
EFI_LOADER_DATA
,
sizeof
(
*
idt
),
(
void
**
)
&
idt
);
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
;
}
...
...
@@ -1204,10 +696,16 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table,
* address, relocate it.
*/
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
)
goto
fail
;
hdr
->
pref_address
=
hdr
->
code32_start
;
hdr
->
code32_start
=
bzimage_addr
;
}
status
=
exit_boot
(
boot_params
,
handle
);
...
...
arch/x86/boot/compressed/eboot.h
View file @
3203209d
...
...
@@ -11,9 +11,6 @@
#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 \
EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, \
0x3f, 0xc1, 0x4d)
...
...
@@ -62,10 +59,4 @@ struct efi_uga_draw_protocol {
void
*
blt
;
};
struct
efi_simple_text_output_protocol
{
void
*
reset
;
void
*
output_string
;
void
*
test_string
;
};
#endif
/* BOOT_COMPRESSED_EBOOT_H */
drivers/firmware/efi/efi-stub-helper.c
0 → 100644
View file @
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
View file @
3203209d
...
...
@@ -39,6 +39,8 @@
typedef
unsigned
long
efi_status_t
;
typedef
u8
efi_bool_t
;
typedef
u16
efi_char16_t
;
/* UNICODE character */
typedef
u64
efi_physical_addr_t
;
typedef
void
*
efi_handle_t
;
typedef
struct
{
...
...
@@ -96,6 +98,7 @@ typedef struct {
#define EFI_MEMORY_DESCRIPTOR_VERSION 1
#define EFI_PAGE_SHIFT 12
#define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT)
typedef
struct
{
u32
type
;
...
...
@@ -157,11 +160,13 @@ typedef struct {
efi_table_hdr_t
hdr
;
void
*
raise_tpl
;
void
*
restore_tpl
;
void
*
allocate_pages
;
void
*
free_pages
;
void
*
get_memory_map
;
void
*
allocate_pool
;
void
*
free_pool
;
efi_status_t
(
*
allocate_pages
)(
int
,
int
,
unsigned
long
,
efi_physical_addr_t
*
);
efi_status_t
(
*
free_pages
)(
efi_physical_addr_t
,
unsigned
long
);
efi_status_t
(
*
get_memory_map
)(
unsigned
long
*
,
void
*
,
unsigned
long
*
,
unsigned
long
*
,
u32
*
);
efi_status_t
(
*
allocate_pool
)(
int
,
unsigned
long
,
void
**
);
efi_status_t
(
*
free_pool
)(
void
*
);
void
*
create_event
;
void
*
set_timer
;
void
*
wait_for_event
;
...
...
@@ -171,7 +176,7 @@ typedef struct {
void
*
install_protocol_interface
;
void
*
reinstall_protocol_interface
;
void
*
uninstall_protocol_interface
;
void
*
handle_protocol
;
efi_status_t
(
*
handle_protocol
)(
efi_handle_t
,
efi_guid_t
*
,
void
**
)
;
void
*
__reserved
;
void
*
register_protocol_notify
;
void
*
locate_handle
;
...
...
@@ -181,7 +186,7 @@ typedef struct {
void
*
start_image
;
void
*
exit
;
void
*
unload_image
;
void
*
exit_boot_services
;
efi_status_t
(
*
exit_boot_services
)(
efi_handle_t
,
unsigned
long
)
;
void
*
get_next_monotonic_count
;
void
*
stall
;
void
*
set_watchdog_timer
;
...
...
@@ -494,10 +499,6 @@ typedef struct {
unsigned
long
unload
;
}
efi_loaded_image_t
;
typedef
struct
{
u64
revision
;
void
*
open_volume
;
}
efi_file_io_interface_t
;
typedef
struct
{
u64
size
;
...
...
@@ -510,20 +511,30 @@ typedef struct {
efi_char16_t
filename
[
1
];
}
efi_file_info_t
;
typedef
struct
{
typedef
struct
_efi_file_handle
{
u64
revision
;
void
*
open
;
void
*
close
;
efi_status_t
(
*
open
)(
struct
_efi_file_handle
*
,
struct
_efi_file_handle
**
,
efi_char16_t
*
,
u64
,
u64
);
efi_status_t
(
*
close
)(
struct
_efi_file_handle
*
);
void
*
delete
;
void
*
read
;
efi_status_t
(
*
read
)(
struct
_efi_file_handle
*
,
unsigned
long
*
,
void
*
);
void
*
write
;
void
*
get_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
*
flush
;
}
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_WRITE 0x0000000000000002
#define EFI_FILE_MODE_CREATE 0x8000000000000000
...
...
@@ -792,6 +803,13 @@ struct efivar_entry {
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
;
static
inline
void
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment