Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
75b12857
K
Kernel
项目概览
openeuler
/
Kernel
大约 1 年 前同步成功
通知
5
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
75b12857
编写于
10月 03, 2014
作者:
M
Matt Fleming
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'next' into efi-next-merge
Conflicts: arch/x86/boot/compressed/eboot.c
上级
fe82dcec
7efe6659
变更
20
显示空白变更内容
内联
并排
Showing
20 changed file
with
528 addition
and
123 deletion
+528
-123
Documentation/kernel-parameters.txt
Documentation/kernel-parameters.txt
+6
-2
arch/arm64/kernel/efi.c
arch/arm64/kernel/efi.c
+18
-26
arch/ia64/kernel/efi.c
arch/ia64/kernel/efi.c
+4
-2
arch/x86/boot/compressed/eboot.c
arch/x86/boot/compressed/eboot.c
+25
-7
arch/x86/include/asm/efi.h
arch/x86/include/asm/efi.h
+10
-21
arch/x86/platform/efi/efi-bgrt.c
arch/x86/platform/efi/efi-bgrt.c
+30
-6
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi.c
+23
-29
arch/x86/platform/efi/efi_32.c
arch/x86/platform/efi/efi_32.c
+7
-5
arch/x86/platform/efi/efi_64.c
arch/x86/platform/efi/efi_64.c
+3
-3
arch/x86/platform/efi/efi_stub_32.S
arch/x86/platform/efi/efi_stub_32.S
+2
-2
drivers/firmware/efi/efi.c
drivers/firmware/efi/efi.c
+79
-0
drivers/firmware/efi/libstub/arm-stub.c
drivers/firmware/efi/libstub/arm-stub.c
+4
-0
drivers/firmware/efi/libstub/efi-stub-helper.c
drivers/firmware/efi/libstub/efi-stub-helper.c
+60
-2
drivers/firmware/efi/runtime-wrappers.c
drivers/firmware/efi/runtime-wrappers.c
+154
-10
drivers/firmware/efi/vars.c
drivers/firmware/efi/vars.c
+54
-7
drivers/rtc/Kconfig
drivers/rtc/Kconfig
+1
-1
drivers/rtc/rtc-efi.c
drivers/rtc/rtc-efi.c
+1
-0
include/linux/efi.h
include/linux/efi.h
+17
-0
include/linux/kernel.h
include/linux/kernel.h
+1
-0
lib/cmdline.c
lib/cmdline.c
+29
-0
未找到文件。
Documentation/kernel-parameters.txt
浏览文件 @
75b12857
...
...
@@ -992,10 +992,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
Format: {"off" | "on" | "skip[mbr]"}
efi= [EFI]
Format: { "old_map" }
Format: { "old_map"
, "nochunk", "noruntime"
}
old_map [X86-64]: switch to the old ioremap-based EFI
runtime services mapping. 32-bit still uses this one by
default.
nochunk: disable reading files in "chunks" in the EFI
boot stub, as chunking can cause problems with some
firmware implementations.
noruntime : disable EFI runtime services support
efi_no_storage_paranoia [EFI; X86]
Using this parameter you can use more than 50% of
...
...
@@ -2166,7 +2170,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
nodsp [SH] Disable hardware DSP at boot time.
noefi
[X86]
Disable EFI runtime services support.
noefi Disable EFI runtime services support.
noexec [IA-64]
...
...
arch/arm64/kernel/efi.c
浏览文件 @
75b12857
...
...
@@ -89,7 +89,8 @@ static int __init uefi_init(void)
*/
if
(
efi
.
systab
->
hdr
.
signature
!=
EFI_SYSTEM_TABLE_SIGNATURE
)
{
pr_err
(
"System table signature incorrect
\n
"
);
return
-
EINVAL
;
retval
=
-
EINVAL
;
goto
out
;
}
if
((
efi
.
systab
->
hdr
.
revision
>>
16
)
<
2
)
pr_warn
(
"Warning: EFI system table version %d.%02d, expected 2.00 or greater
\n
"
,
...
...
@@ -103,6 +104,7 @@ static int __init uefi_init(void)
for
(
i
=
0
;
i
<
(
int
)
sizeof
(
vendor
)
-
1
&&
*
c16
;
++
i
)
vendor
[
i
]
=
c16
[
i
];
vendor
[
i
]
=
'\0'
;
early_memunmap
(
c16
,
sizeof
(
vendor
));
}
pr_info
(
"EFI v%u.%.02u by %s
\n
"
,
...
...
@@ -113,29 +115,11 @@ static int __init uefi_init(void)
if
(
retval
==
0
)
set_bit
(
EFI_CONFIG_TABLES
,
&
efi
.
flags
);
early_memunmap
(
c16
,
sizeof
(
vendor
));
out:
early_memunmap
(
efi
.
systab
,
sizeof
(
efi_system_table_t
));
return
retval
;
}
static
__initdata
char
memory_type_name
[][
32
]
=
{
{
"Reserved"
},
{
"Loader Code"
},
{
"Loader Data"
},
{
"Boot Code"
},
{
"Boot Data"
},
{
"Runtime Code"
},
{
"Runtime Data"
},
{
"Conventional Memory"
},
{
"Unusable Memory"
},
{
"ACPI Reclaim Memory"
},
{
"ACPI Memory NVS"
},
{
"Memory Mapped I/O"
},
{
"MMIO Port Space"
},
{
"PAL Code"
},
};
/*
* Return true for RAM regions we want to permanently reserve.
*/
...
...
@@ -166,10 +150,13 @@ static __init void reserve_regions(void)
paddr
=
md
->
phys_addr
;
npages
=
md
->
num_pages
;
if
(
uefi_debug
)
pr_info
(
" 0x%012llx-0x%012llx [%s]"
,
if
(
uefi_debug
)
{
char
buf
[
64
];
pr_info
(
" 0x%012llx-0x%012llx %s"
,
paddr
,
paddr
+
(
npages
<<
EFI_PAGE_SHIFT
)
-
1
,
memory_type_name
[
md
->
type
]);
efi_md_typeattr_format
(
buf
,
sizeof
(
buf
),
md
));
}
memrange_efi_to_native
(
&
paddr
,
&
npages
);
size
=
npages
<<
PAGE_SHIFT
;
...
...
@@ -393,11 +380,16 @@ static int __init arm64_enter_virtual_mode(void)
return
-
1
;
}
pr_info
(
"Remapping and enabling EFI services.
\n
"
);
/* replace early memmap mapping with permanent mapping */
mapsize
=
memmap
.
map_end
-
memmap
.
map
;
early_memunmap
(
memmap
.
map
,
mapsize
);
if
(
efi_runtime_disabled
())
{
pr_info
(
"EFI runtime services will be disabled.
\n
"
);
return
-
1
;
}
pr_info
(
"Remapping and enabling EFI services.
\n
"
);
/* replace early memmap mapping with permanent mapping */
memmap
.
map
=
(
__force
void
*
)
ioremap_cache
((
phys_addr_t
)
memmap
.
phys_map
,
mapsize
);
memmap
.
map_end
=
memmap
.
map
+
mapsize
;
...
...
arch/ia64/kernel/efi.c
浏览文件 @
75b12857
...
...
@@ -568,6 +568,7 @@ efi_init (void)
{
const
char
*
unit
;
unsigned
long
size
;
char
buf
[
64
];
md
=
p
;
size
=
md
->
num_pages
<<
EFI_PAGE_SHIFT
;
...
...
@@ -586,9 +587,10 @@ efi_init (void)
unit
=
"KB"
;
}
printk
(
"mem%02d:
type=%2u, attr=0x%016lx,
"
printk
(
"mem%02d:
%s
"
"range=[0x%016lx-0x%016lx) (%4lu%s)
\n
"
,
i
,
md
->
type
,
md
->
attribute
,
md
->
phys_addr
,
i
,
efi_md_typeattr_format
(
buf
,
sizeof
(
buf
),
md
),
md
->
phys_addr
,
md
->
phys_addr
+
efi_md_size
(
md
),
size
,
unit
);
}
}
...
...
arch/x86/boot/compressed/eboot.c
浏览文件 @
75b12857
...
...
@@ -330,8 +330,10 @@ __setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct pci_setup_rom **__rom)
size
=
pci
->
romsize
+
sizeof
(
*
rom
);
status
=
efi_call_early
(
allocate_pool
,
EFI_LOADER_DATA
,
size
,
&
rom
);
if
(
status
!=
EFI_SUCCESS
)
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
sys_table
,
"Failed to alloc mem for rom
\n
"
);
return
status
;
}
memset
(
rom
,
0
,
sizeof
(
*
rom
));
...
...
@@ -344,14 +346,18 @@ __setup_efi_pci32(efi_pci_io_protocol_32 *pci, struct pci_setup_rom **__rom)
status
=
efi_early
->
call
(
pci
->
pci
.
read
,
pci
,
EfiPciIoWidthUint16
,
PCI_VENDOR_ID
,
1
,
&
(
rom
->
vendor
));
if
(
status
!=
EFI_SUCCESS
)
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
sys_table
,
"Failed to read rom->vendor
\n
"
);
goto
free_struct
;
}
status
=
efi_early
->
call
(
pci
->
pci
.
read
,
pci
,
EfiPciIoWidthUint16
,
PCI_DEVICE_ID
,
1
,
&
(
rom
->
devid
));
if
(
status
!=
EFI_SUCCESS
)
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
sys_table
,
"Failed to read rom->devid
\n
"
);
goto
free_struct
;
}
status
=
efi_early
->
call
(
pci
->
get_location
,
pci
,
&
(
rom
->
segment
),
&
(
rom
->
bus
),
&
(
rom
->
device
),
&
(
rom
->
function
));
...
...
@@ -432,8 +438,10 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct pci_setup_rom **__rom)
size
=
pci
->
romsize
+
sizeof
(
*
rom
);
status
=
efi_call_early
(
allocate_pool
,
EFI_LOADER_DATA
,
size
,
&
rom
);
if
(
status
!=
EFI_SUCCESS
)
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
sys_table
,
"Failed to alloc mem for rom
\n
"
);
return
status
;
}
rom
->
data
.
type
=
SETUP_PCI
;
rom
->
data
.
len
=
size
-
sizeof
(
struct
setup_data
);
...
...
@@ -444,14 +452,18 @@ __setup_efi_pci64(efi_pci_io_protocol_64 *pci, struct pci_setup_rom **__rom)
status
=
efi_early
->
call
(
pci
->
pci
.
read
,
pci
,
EfiPciIoWidthUint16
,
PCI_VENDOR_ID
,
1
,
&
(
rom
->
vendor
));
if
(
status
!=
EFI_SUCCESS
)
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
sys_table
,
"Failed to read rom->vendor
\n
"
);
goto
free_struct
;
}
status
=
efi_early
->
call
(
pci
->
pci
.
read
,
pci
,
EfiPciIoWidthUint16
,
PCI_DEVICE_ID
,
1
,
&
(
rom
->
devid
));
if
(
status
!=
EFI_SUCCESS
)
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
sys_table
,
"Failed to read rom->devid
\n
"
);
goto
free_struct
;
}
status
=
efi_early
->
call
(
pci
->
get_location
,
pci
,
&
(
rom
->
segment
),
&
(
rom
->
bus
),
&
(
rom
->
device
),
&
(
rom
->
function
));
...
...
@@ -538,8 +550,10 @@ static void setup_efi_pci(struct boot_params *params)
EFI_LOADER_DATA
,
size
,
(
void
**
)
&
pci_handle
);
if
(
status
!=
EFI_SUCCESS
)
if
(
status
!=
EFI_SUCCESS
)
{
efi_printk
(
sys_table
,
"Failed to alloc mem for pci_handle
\n
"
);
return
;
}
status
=
efi_call_early
(
locate_handle
,
EFI_LOCATE_BY_PROTOCOL
,
&
pci_proto
,
...
...
@@ -1105,6 +1119,10 @@ struct boot_params *make_boot_params(struct efi_config *c)
memset
(
sdt
,
0
,
sizeof
(
*
sdt
));
status
=
efi_parse_options
(
cmdline_ptr
);
if
(
status
!=
EFI_SUCCESS
)
goto
fail2
;
status
=
handle_cmdline_files
(
sys_table
,
image
,
(
char
*
)(
unsigned
long
)
hdr
->
cmd_line_ptr
,
"initrd="
,
hdr
->
initrd_addr_max
,
...
...
arch/x86/include/asm/efi.h
浏览文件 @
75b12857
...
...
@@ -81,24 +81,23 @@ extern u64 asmlinkage efi_call(void *fp, ...);
*/
#define __efi_call_virt(f, args...) efi_call_virt(f, args)
extern
void
__iomem
*
efi_ioremap
(
unsigned
long
addr
,
unsigned
long
size
,
extern
void
__iomem
*
__init
efi_ioremap
(
unsigned
long
addr
,
unsigned
long
size
,
u32
type
,
u64
attribute
);
#endif
/* CONFIG_X86_32 */
extern
int
add_efi_memmap
;
extern
struct
efi_scratch
efi_scratch
;
extern
void
efi_set_executable
(
efi_memory_desc_t
*
md
,
bool
executable
);
extern
int
efi_memblock_x86_reserve_range
(
void
);
extern
void
efi_call_phys_pre
log
(
void
);
extern
void
efi_call_phys_epilog
(
void
);
extern
void
efi_unmap_memmap
(
void
);
extern
void
efi_memory_uc
(
u64
addr
,
unsigned
long
size
);
extern
void
__init
efi_set_executable
(
efi_memory_desc_t
*
md
,
bool
executable
);
extern
int
__init
efi_memblock_x86_reserve_range
(
void
);
extern
void
__init
efi_call_phys_pro
log
(
void
);
extern
void
__init
efi_call_phys_epilog
(
void
);
extern
void
__init
efi_unmap_memmap
(
void
);
extern
void
__init
efi_memory_uc
(
u64
addr
,
unsigned
long
size
);
extern
void
__init
efi_map_region
(
efi_memory_desc_t
*
md
);
extern
void
__init
efi_map_region_fixed
(
efi_memory_desc_t
*
md
);
extern
void
efi_sync_low_kernel_mappings
(
void
);
extern
int
efi_setup_page_tables
(
unsigned
long
pa_memmap
,
unsigned
num_pages
);
extern
void
efi_cleanup_page_tables
(
unsigned
long
pa_memmap
,
unsigned
num_pages
);
extern
int
__init
efi_setup_page_tables
(
unsigned
long
pa_memmap
,
unsigned
num_pages
);
extern
void
__init
efi_cleanup_page_tables
(
unsigned
long
pa_memmap
,
unsigned
num_pages
);
extern
void
__init
old_map_region
(
efi_memory_desc_t
*
md
);
extern
void
__init
runtime_code_page_mkexec
(
void
);
extern
void
__init
efi_runtime_mkexec
(
void
);
...
...
@@ -162,16 +161,6 @@ static inline efi_status_t efi_thunk_set_virtual_address_map(
extern
bool
efi_reboot_required
(
void
);
#else
/*
* IF EFI is not configured, have the EFI calls return -ENOSYS.
*/
#define efi_call0(_f) (-ENOSYS)
#define efi_call1(_f, _a1) (-ENOSYS)
#define efi_call2(_f, _a1, _a2) (-ENOSYS)
#define efi_call3(_f, _a1, _a2, _a3) (-ENOSYS)
#define efi_call4(_f, _a1, _a2, _a3, _a4) (-ENOSYS)
#define efi_call5(_f, _a1, _a2, _a3, _a4, _a5) (-ENOSYS)
#define efi_call6(_f, _a1, _a2, _a3, _a4, _a5, _a6) (-ENOSYS)
static
inline
void
parse_efi_setup
(
u64
phys_addr
,
u32
data_len
)
{}
static
inline
bool
efi_reboot_required
(
void
)
{
...
...
arch/x86/platform/efi/efi-bgrt.c
浏览文件 @
75b12857
...
...
@@ -40,35 +40,59 @@ void __init efi_bgrt_init(void)
if
(
ACPI_FAILURE
(
status
))
return
;
if
(
bgrt_tab
->
header
.
length
<
sizeof
(
*
bgrt_tab
))
if
(
bgrt_tab
->
header
.
length
<
sizeof
(
*
bgrt_tab
))
{
pr_err
(
"Ignoring BGRT: invalid length %u (expected %zu)
\n
"
,
bgrt_tab
->
header
.
length
,
sizeof
(
*
bgrt_tab
));
return
;
if
(
bgrt_tab
->
version
!=
1
||
bgrt_tab
->
status
!=
1
)
}
if
(
bgrt_tab
->
version
!=
1
)
{
pr_err
(
"Ignoring BGRT: invalid version %u (expected 1)
\n
"
,
bgrt_tab
->
version
);
return
;
}
if
(
bgrt_tab
->
status
!=
1
)
{
pr_err
(
"Ignoring BGRT: invalid status %u (expected 1)
\n
"
,
bgrt_tab
->
status
);
return
;
}
if
(
bgrt_tab
->
image_type
!=
0
)
{
pr_err
(
"Ignoring BGRT: invalid image type %u (expected 0)
\n
"
,
bgrt_tab
->
image_type
);
return
;
if
(
bgrt_tab
->
image_type
!=
0
||
!
bgrt_tab
->
image_address
)
}
if
(
!
bgrt_tab
->
image_address
)
{
pr_err
(
"Ignoring BGRT: null image address
\n
"
);
return
;
}
image
=
efi_lookup_mapped_addr
(
bgrt_tab
->
image_address
);
if
(
!
image
)
{
image
=
early_memremap
(
bgrt_tab
->
image_address
,
sizeof
(
bmp_header
));
ioremapped
=
true
;
if
(
!
image
)
if
(
!
image
)
{
pr_err
(
"Ignoring BGRT: failed to map image header memory
\n
"
);
return
;
}
}
memcpy_fromio
(
&
bmp_header
,
image
,
sizeof
(
bmp_header
));
if
(
ioremapped
)
early_iounmap
(
image
,
sizeof
(
bmp_header
));
bgrt_image_size
=
bmp_header
.
size
;
bgrt_image
=
kmalloc
(
bgrt_image_size
,
GFP_KERNEL
);
if
(
!
bgrt_image
)
bgrt_image
=
kmalloc
(
bgrt_image_size
,
GFP_KERNEL
|
__GFP_NOWARN
);
if
(
!
bgrt_image
)
{
pr_err
(
"Ignoring BGRT: failed to allocate memory for image (wanted %zu bytes)
\n
"
,
bgrt_image_size
);
return
;
}
if
(
ioremapped
)
{
image
=
early_memremap
(
bgrt_tab
->
image_address
,
bmp_header
.
size
);
if
(
!
image
)
{
pr_err
(
"Ignoring BGRT: failed to map image memory
\n
"
);
kfree
(
bgrt_image
);
bgrt_image
=
NULL
;
return
;
...
...
arch/x86/platform/efi/efi.c
浏览文件 @
75b12857
...
...
@@ -70,17 +70,7 @@ static efi_config_table_type_t arch_tables[] __initdata = {
u64
efi_setup
;
/* efi setup_data physical address */
static
bool
disable_runtime
__initdata
=
false
;
static
int
__init
setup_noefi
(
char
*
arg
)
{
disable_runtime
=
true
;
return
0
;
}
early_param
(
"noefi"
,
setup_noefi
);
int
add_efi_memmap
;
EXPORT_SYMBOL
(
add_efi_memmap
);
static
int
add_efi_memmap
__initdata
;
static
int
__init
setup_add_efi_memmap
(
char
*
arg
)
{
add_efi_memmap
=
1
;
...
...
@@ -96,7 +86,7 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
{
efi_status_t
status
;
efi_call_phys_pr
e
log
();
efi_call_phys_pr
o
log
();
status
=
efi_call_phys
(
efi_phys
.
set_virtual_address_map
,
memory_map_size
,
descriptor_size
,
descriptor_version
,
virtual_map
);
...
...
@@ -210,9 +200,12 @@ static void __init print_efi_memmap(void)
for
(
p
=
memmap
.
map
,
i
=
0
;
p
<
memmap
.
map_end
;
p
+=
memmap
.
desc_size
,
i
++
)
{
char
buf
[
64
];
md
=
p
;
pr_info
(
"mem%02u: type=%u, attr=0x%llx, range=[0x%016llx-0x%016llx) (%lluMB)
\n
"
,
i
,
md
->
type
,
md
->
attribute
,
md
->
phys_addr
,
pr_info
(
"mem%02u: %s range=[0x%016llx-0x%016llx) (%lluMB)
\n
"
,
i
,
efi_md_typeattr_format
(
buf
,
sizeof
(
buf
),
md
),
md
->
phys_addr
,
md
->
phys_addr
+
(
md
->
num_pages
<<
EFI_PAGE_SHIFT
),
(
md
->
num_pages
>>
(
20
-
EFI_PAGE_SHIFT
)));
}
...
...
@@ -344,9 +337,9 @@ static int __init efi_runtime_init32(void)
}
/*
* We will only need *early* access to the
following two
* EFI runtime service
s before set_virtual_address_map
*
is invoked
.
* We will only need *early* access to the
SetVirtualAddressMap
* EFI runtime service
. All other runtime services will be called
*
via the virtual mapping
.
*/
efi_phys
.
set_virtual_address_map
=
(
efi_set_virtual_address_map_t
*
)
...
...
@@ -368,9 +361,9 @@ static int __init efi_runtime_init64(void)
}
/*
* We will only need *early* access to the
following two
* EFI runtime service
s before set_virtual_address_map
*
is invoked
.
* We will only need *early* access to the
SetVirtualAddressMap
* EFI runtime service
. All other runtime services will be called
*
via the virtual mapping
.
*/
efi_phys
.
set_virtual_address_map
=
(
efi_set_virtual_address_map_t
*
)
...
...
@@ -492,7 +485,7 @@ void __init efi_init(void)
if
(
!
efi_runtime_supported
())
pr_info
(
"No EFI runtime due to 32/64-bit mismatch with kernel
\n
"
);
else
{
if
(
disable_runtime
||
efi_runtime_init
())
if
(
efi_runtime_disabled
()
||
efi_runtime_init
())
return
;
}
if
(
efi_memmap_init
())
...
...
@@ -537,7 +530,7 @@ void __init runtime_code_page_mkexec(void)
}
}
void
efi_memory_uc
(
u64
addr
,
unsigned
long
size
)
void
__init
efi_memory_uc
(
u64
addr
,
unsigned
long
size
)
{
unsigned
long
page_shift
=
1UL
<<
EFI_PAGE_SHIFT
;
u64
npages
;
...
...
@@ -732,6 +725,7 @@ static void __init kexec_enter_virtual_mode(void)
*/
if
(
!
efi_is_native
())
{
efi_unmap_memmap
();
clear_bit
(
EFI_RUNTIME_SERVICES
,
&
efi
.
flags
);
return
;
}
...
...
@@ -805,6 +799,7 @@ static void __init __efi_enter_virtual_mode(void)
new_memmap
=
efi_map_regions
(
&
count
,
&
pg_shift
);
if
(
!
new_memmap
)
{
pr_err
(
"Error reallocating memory, EFI runtime non-functional!
\n
"
);
clear_bit
(
EFI_RUNTIME_SERVICES
,
&
efi
.
flags
);
return
;
}
...
...
@@ -812,8 +807,10 @@ static void __init __efi_enter_virtual_mode(void)
BUG_ON
(
!
efi
.
systab
);
if
(
efi_setup_page_tables
(
__pa
(
new_memmap
),
1
<<
pg_shift
))
if
(
efi_setup_page_tables
(
__pa
(
new_memmap
),
1
<<
pg_shift
))
{
clear_bit
(
EFI_RUNTIME_SERVICES
,
&
efi
.
flags
);
return
;
}
efi_sync_low_kernel_mappings
();
efi_dump_pagetable
();
...
...
@@ -938,14 +935,11 @@ u64 efi_mem_attributes(unsigned long phys_addr)
return
0
;
}
static
int
__init
parse_efi_cmdline
(
char
*
str
)
static
int
__init
arch_
parse_efi_cmdline
(
char
*
str
)
{
if
(
*
str
==
'='
)
str
++
;
if
(
!
strncmp
(
str
,
"old_map"
,
7
))
if
(
parse_option_str
(
str
,
"old_map"
))
set_bit
(
EFI_OLD_MEMMAP
,
&
efi
.
flags
);
return
0
;
}
early_param
(
"efi"
,
parse_efi_cmdline
);
early_param
(
"efi"
,
arch_
parse_efi_cmdline
);
arch/x86/platform/efi/efi_32.c
浏览文件 @
75b12857
...
...
@@ -33,7 +33,7 @@
/*
* To make EFI call EFI runtime service in physical addressing mode we need
* pr
e
log/epilog before/after the invocation to disable interrupt, to
* pr
o
log/epilog before/after the invocation to disable interrupt, to
* claim EFI runtime service handler exclusively and to duplicate a memory in
* low memory space say 0 - 3G.
*/
...
...
@@ -41,11 +41,13 @@ static unsigned long efi_rt_eflags;
void
efi_sync_low_kernel_mappings
(
void
)
{}
void
__init
efi_dump_pagetable
(
void
)
{}
int
efi_setup_page_tables
(
unsigned
long
pa_memmap
,
unsigned
num_pages
)
int
__init
efi_setup_page_tables
(
unsigned
long
pa_memmap
,
unsigned
num_pages
)
{
return
0
;
}
void
efi_cleanup_page_tables
(
unsigned
long
pa_memmap
,
unsigned
num_pages
)
{}
void
__init
efi_cleanup_page_tables
(
unsigned
long
pa_memmap
,
unsigned
num_pages
)
{
}
void
__init
efi_map_region
(
efi_memory_desc_t
*
md
)
{
...
...
@@ -55,7 +57,7 @@ void __init efi_map_region(efi_memory_desc_t *md)
void
__init
efi_map_region_fixed
(
efi_memory_desc_t
*
md
)
{}
void
__init
parse_efi_setup
(
u64
phys_addr
,
u32
data_len
)
{}
void
efi_call_phys_pre
log
(
void
)
void
__init
efi_call_phys_pro
log
(
void
)
{
struct
desc_ptr
gdt_descr
;
...
...
@@ -69,7 +71,7 @@ void efi_call_phys_prelog(void)
load_gdt
(
&
gdt_descr
);
}
void
efi_call_phys_epilog
(
void
)
void
__init
efi_call_phys_epilog
(
void
)
{
struct
desc_ptr
gdt_descr
;
...
...
arch/x86/platform/efi/efi_64.c
浏览文件 @
75b12857
...
...
@@ -79,7 +79,7 @@ static void __init early_code_mapping_set_exec(int executable)
}
}
void
__init
efi_call_phys_pr
e
log
(
void
)
void
__init
efi_call_phys_pr
o
log
(
void
)
{
unsigned
long
vaddress
;
int
pgd
;
...
...
@@ -139,7 +139,7 @@ void efi_sync_low_kernel_mappings(void)
sizeof
(
pgd_t
)
*
num_pgds
);
}
int
efi_setup_page_tables
(
unsigned
long
pa_memmap
,
unsigned
num_pages
)
int
__init
efi_setup_page_tables
(
unsigned
long
pa_memmap
,
unsigned
num_pages
)
{
unsigned
long
text
;
struct
page
*
page
;
...
...
@@ -192,7 +192,7 @@ int efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
return
0
;
}
void
efi_cleanup_page_tables
(
unsigned
long
pa_memmap
,
unsigned
num_pages
)
void
__init
efi_cleanup_page_tables
(
unsigned
long
pa_memmap
,
unsigned
num_pages
)
{
pgd_t
*
pgd
=
(
pgd_t
*
)
__va
(
real_mode_header
->
trampoline_pgd
);
...
...
arch/x86/platform/efi/efi_stub_32.S
浏览文件 @
75b12857
...
...
@@ -27,13 +27,13 @@ ENTRY(efi_call_phys)
*
set
to
0x0010
,
DS
and
SS
have
been
set
to
0x0018
.
In
EFI
,
I
found
*
the
values
of
these
registers
are
the
same
.
And
,
the
corresponding
*
GDT
entries
are
identical
.
So
I
will
do
nothing
about
segment
reg
*
and
GDT
,
but
change
GDT
base
register
in
pr
e
log
and
epilog
.
*
and
GDT
,
but
change
GDT
base
register
in
pr
o
log
and
epilog
.
*/
/
*
*
1
.
Now
I
am
running
with
EIP
=
<
physical
address
>
+
PAGE_OFFSET
.
*
But
to
make
it
smoothly
switch
from
virtual
mode
to
flat
mode
.
*
The
mapping
of
lower
virtual
memory
has
been
created
in
pr
e
log
and
*
The
mapping
of
lower
virtual
memory
has
been
created
in
pr
o
log
and
*
epilog
.
*/
movl
$
1
f
,
%
edx
...
...
drivers/firmware/efi/efi.c
浏览文件 @
75b12857
...
...
@@ -41,6 +41,28 @@ struct efi __read_mostly efi = {
};
EXPORT_SYMBOL
(
efi
);
static
bool
disable_runtime
;
static
int
__init
setup_noefi
(
char
*
arg
)
{
disable_runtime
=
true
;
return
0
;
}
early_param
(
"noefi"
,
setup_noefi
);
bool
efi_runtime_disabled
(
void
)
{
return
disable_runtime
;
}
static
int
__init
parse_efi_cmdline
(
char
*
str
)
{
if
(
parse_option_str
(
str
,
"noruntime"
))
disable_runtime
=
true
;
return
0
;
}
early_param
(
"efi"
,
parse_efi_cmdline
);
static
struct
kobject
*
efi_kobj
;
static
struct
kobject
*
efivars_kobj
;
...
...
@@ -423,3 +445,60 @@ int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose)
return
ret
;
}
#endif
/* CONFIG_EFI_PARAMS_FROM_FDT */
static
__initdata
char
memory_type_name
[][
20
]
=
{
"Reserved"
,
"Loader Code"
,
"Loader Data"
,
"Boot Code"
,
"Boot Data"
,
"Runtime Code"
,
"Runtime Data"
,
"Conventional Memory"
,
"Unusable Memory"
,
"ACPI Reclaim Memory"
,
"ACPI Memory NVS"
,
"Memory Mapped I/O"
,
"MMIO Port Space"
,
"PAL Code"
};
char
*
__init
efi_md_typeattr_format
(
char
*
buf
,
size_t
size
,
const
efi_memory_desc_t
*
md
)
{
char
*
pos
;
int
type_len
;
u64
attr
;
pos
=
buf
;
if
(
md
->
type
>=
ARRAY_SIZE
(
memory_type_name
))
type_len
=
snprintf
(
pos
,
size
,
"[type=%u"
,
md
->
type
);
else
type_len
=
snprintf
(
pos
,
size
,
"[%-*s"
,
(
int
)(
sizeof
(
memory_type_name
[
0
])
-
1
),
memory_type_name
[
md
->
type
]);
if
(
type_len
>=
size
)
return
buf
;
pos
+=
type_len
;
size
-=
type_len
;
attr
=
md
->
attribute
;
if
(
attr
&
~
(
EFI_MEMORY_UC
|
EFI_MEMORY_WC
|
EFI_MEMORY_WT
|
EFI_MEMORY_WB
|
EFI_MEMORY_UCE
|
EFI_MEMORY_WP
|
EFI_MEMORY_RP
|
EFI_MEMORY_XP
|
EFI_MEMORY_RUNTIME
))
snprintf
(
pos
,
size
,
"|attr=0x%016llx]"
,
(
unsigned
long
long
)
attr
);
else
snprintf
(
pos
,
size
,
"|%3s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]"
,
attr
&
EFI_MEMORY_RUNTIME
?
"RUN"
:
""
,
attr
&
EFI_MEMORY_XP
?
"XP"
:
""
,
attr
&
EFI_MEMORY_RP
?
"RP"
:
""
,
attr
&
EFI_MEMORY_WP
?
"WP"
:
""
,
attr
&
EFI_MEMORY_UCE
?
"UCE"
:
""
,
attr
&
EFI_MEMORY_WB
?
"WB"
:
""
,
attr
&
EFI_MEMORY_WT
?
"WT"
:
""
,
attr
&
EFI_MEMORY_WC
?
"WC"
:
""
,
attr
&
EFI_MEMORY_UC
?
"UC"
:
""
);
return
buf
;
}
drivers/firmware/efi/libstub/arm-stub.c
浏览文件 @
75b12857
...
...
@@ -226,6 +226,10 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
goto
fail_free_image
;
}
status
=
efi_parse_options
(
cmdline_ptr
);
if
(
status
!=
EFI_SUCCESS
)
pr_efi_err
(
sys_table
,
"Failed to parse EFI cmdline options
\n
"
);
/*
* Unauthenticated device tree data is a security hazard, so
* ignore 'dtb=' unless UEFI Secure Boot is disabled.
...
...
drivers/firmware/efi/libstub/efi-stub-helper.c
浏览文件 @
75b12857
...
...
@@ -15,8 +15,23 @@
#include "efistub.h"
/*
* Some firmware implementations have problems reading files in one go.
* A read chunk size of 1MB seems to work for most platforms.
*
* Unfortunately, reading files in chunks triggers *other* bugs on some
* platforms, so we provide a way to disable this workaround, which can
* be done by passing "efi=nochunk" on the EFI boot stub command line.
*
* If you experience issues with initrd images being corrupt it's worth
* trying efi=nochunk, but chunking is enabled by default because there
* are far more machines that require the workaround than those that
* break with it enabled.
*/
#define EFI_READ_CHUNK_SIZE (1024 * 1024)
static
unsigned
long
__chunk_size
=
EFI_READ_CHUNK_SIZE
;
struct
file_info
{
efi_file_handle_t
*
handle
;
u64
size
;
...
...
@@ -281,6 +296,49 @@ void efi_free(efi_system_table_t *sys_table_arg, unsigned long size,
efi_call_early
(
free_pages
,
addr
,
nr_pages
);
}
/*
* Parse the ASCII string 'cmdline' for EFI options, denoted by the efi=
* option, e.g. efi=nochunk.
*
* It should be noted that efi= is parsed in two very different
* environments, first in the early boot environment of the EFI boot
* stub, and subsequently during the kernel boot.
*/
efi_status_t
efi_parse_options
(
char
*
cmdline
)
{
char
*
str
;
/*
* If no EFI parameters were specified on the cmdline we've got
* nothing to do.
*/
str
=
strstr
(
cmdline
,
"efi="
);
if
(
!
str
)
return
EFI_SUCCESS
;
/* Skip ahead to first argument */
str
+=
strlen
(
"efi="
);
/*
* Remember, because efi= is also used by the kernel we need to
* skip over arguments we don't understand.
*/
while
(
*
str
)
{
if
(
!
strncmp
(
str
,
"nochunk"
,
7
))
{
str
+=
strlen
(
"nochunk"
);
__chunk_size
=
-
1UL
;
}
/* Group words together, delimited by "," */
while
(
*
str
&&
*
str
!=
','
)
str
++
;
if
(
*
str
==
','
)
str
++
;
}
return
EFI_SUCCESS
;
}
/*
* Check the cmdline for a LILO-style file= arguments.
...
...
@@ -423,8 +481,8 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
size
=
files
[
j
].
size
;
while
(
size
)
{
unsigned
long
chunksize
;
if
(
size
>
EFI_READ_CHUNK_SIZE
)
chunksize
=
EFI_READ_CHUNK_SIZE
;
if
(
size
>
__chunk_size
)
chunksize
=
__chunk_size
;
else
chunksize
=
size
;
...
...
drivers/firmware/efi/runtime-wrappers.c
浏览文件 @
75b12857
...
...
@@ -14,10 +14,79 @@
* This file is released under the GPLv2.
*/
#include <linux/bug.h>
#include <linux/efi.h>
#include <linux/spinlock.h>
/* spinlock_t */
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <asm/efi.h>
/*
* According to section 7.1 of the UEFI spec, Runtime Services are not fully
* reentrant, and there are particular combinations of calls that need to be
* serialized. (source: UEFI Specification v2.4A)
*
* Table 31. Rules for Reentry Into Runtime Services
* +------------------------------------+-------------------------------+
* | If previous call is busy in | Forbidden to call |
* +------------------------------------+-------------------------------+
* | Any | SetVirtualAddressMap() |
* +------------------------------------+-------------------------------+
* | ConvertPointer() | ConvertPointer() |
* +------------------------------------+-------------------------------+
* | SetVariable() | ResetSystem() |
* | UpdateCapsule() | |
* | SetTime() | |
* | SetWakeupTime() | |
* | GetNextHighMonotonicCount() | |
* +------------------------------------+-------------------------------+
* | GetVariable() | GetVariable() |
* | GetNextVariableName() | GetNextVariableName() |
* | SetVariable() | SetVariable() |
* | QueryVariableInfo() | QueryVariableInfo() |
* | UpdateCapsule() | UpdateCapsule() |
* | QueryCapsuleCapabilities() | QueryCapsuleCapabilities() |
* | GetNextHighMonotonicCount() | GetNextHighMonotonicCount() |
* +------------------------------------+-------------------------------+
* | GetTime() | GetTime() |
* | SetTime() | SetTime() |
* | GetWakeupTime() | GetWakeupTime() |
* | SetWakeupTime() | SetWakeupTime() |
* +------------------------------------+-------------------------------+
*
* Due to the fact that the EFI pstore may write to the variable store in
* interrupt context, we need to use a spinlock for at least the groups that
* contain SetVariable() and QueryVariableInfo(). That leaves little else, as
* none of the remaining functions are actually ever called at runtime.
* So let's just use a single spinlock to serialize all Runtime Services calls.
*/
static
DEFINE_SPINLOCK
(
efi_runtime_lock
);
/*
* Some runtime services calls can be reentrant under NMI, even if the table
* above says they are not. (source: UEFI Specification v2.4A)
*
* Table 32. Functions that may be called after Machine Check, INIT and NMI
* +----------------------------+------------------------------------------+
* | Function | Called after Machine Check, INIT and NMI |
* +----------------------------+------------------------------------------+
* | GetTime() | Yes, even if previously busy. |
* | GetVariable() | Yes, even if previously busy |
* | GetNextVariableName() | Yes, even if previously busy |
* | QueryVariableInfo() | Yes, even if previously busy |
* | SetVariable() | Yes, even if previously busy |
* | UpdateCapsule() | Yes, even if previously busy |
* | QueryCapsuleCapabilities() | Yes, even if previously busy |
* | ResetSystem() | Yes, even if previously busy |
* +----------------------------+------------------------------------------+
*
* In order to prevent deadlocks under NMI, the wrappers for these functions
* may only grab the efi_runtime_lock or rtc_lock spinlocks if !efi_in_nmi().
* However, not all of the services listed are reachable through NMI code paths,
* so the the special handling as suggested by the UEFI spec is only implemented
* for QueryVariableInfo() and SetVariable(), as these can be reached in NMI
* context through efi_pstore_write().
*/
/*
* As per commit ef68c8f87ed1 ("x86: Serialize EFI time accesses on rtc_lock"),
* the EFI specification requires that callers of the time related runtime
...
...
@@ -32,7 +101,9 @@ static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
efi_status_t
status
;
spin_lock_irqsave
(
&
rtc_lock
,
flags
);
spin_lock
(
&
efi_runtime_lock
);
status
=
efi_call_virt
(
get_time
,
tm
,
tc
);
spin_unlock
(
&
efi_runtime_lock
);
spin_unlock_irqrestore
(
&
rtc_lock
,
flags
);
return
status
;
}
...
...
@@ -43,7 +114,9 @@ static efi_status_t virt_efi_set_time(efi_time_t *tm)
efi_status_t
status
;
spin_lock_irqsave
(
&
rtc_lock
,
flags
);
spin_lock
(
&
efi_runtime_lock
);
status
=
efi_call_virt
(
set_time
,
tm
);
spin_unlock
(
&
efi_runtime_lock
);
spin_unlock_irqrestore
(
&
rtc_lock
,
flags
);
return
status
;
}
...
...
@@ -56,7 +129,9 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
efi_status_t
status
;
spin_lock_irqsave
(
&
rtc_lock
,
flags
);
spin_lock
(
&
efi_runtime_lock
);
status
=
efi_call_virt
(
get_wakeup_time
,
enabled
,
pending
,
tm
);
spin_unlock
(
&
efi_runtime_lock
);
spin_unlock_irqrestore
(
&
rtc_lock
,
flags
);
return
status
;
}
...
...
@@ -67,7 +142,9 @@ static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
efi_status_t
status
;
spin_lock_irqsave
(
&
rtc_lock
,
flags
);
spin_lock
(
&
efi_runtime_lock
);
status
=
efi_call_virt
(
set_wakeup_time
,
enabled
,
tm
);
spin_unlock
(
&
efi_runtime_lock
);
spin_unlock_irqrestore
(
&
rtc_lock
,
flags
);
return
status
;
}
...
...
@@ -78,14 +155,27 @@ static efi_status_t virt_efi_get_variable(efi_char16_t *name,
unsigned
long
*
data_size
,
void
*
data
)
{
return
efi_call_virt
(
get_variable
,
name
,
vendor
,
attr
,
data_size
,
data
);
unsigned
long
flags
;
efi_status_t
status
;
spin_lock_irqsave
(
&
efi_runtime_lock
,
flags
);
status
=
efi_call_virt
(
get_variable
,
name
,
vendor
,
attr
,
data_size
,
data
);
spin_unlock_irqrestore
(
&
efi_runtime_lock
,
flags
);
return
status
;
}
static
efi_status_t
virt_efi_get_next_variable
(
unsigned
long
*
name_size
,
efi_char16_t
*
name
,
efi_guid_t
*
vendor
)
{
return
efi_call_virt
(
get_next_variable
,
name_size
,
name
,
vendor
);
unsigned
long
flags
;
efi_status_t
status
;
spin_lock_irqsave
(
&
efi_runtime_lock
,
flags
);
status
=
efi_call_virt
(
get_next_variable
,
name_size
,
name
,
vendor
);
spin_unlock_irqrestore
(
&
efi_runtime_lock
,
flags
);
return
status
;
}
static
efi_status_t
virt_efi_set_variable
(
efi_char16_t
*
name
,
...
...
@@ -94,24 +184,61 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
unsigned
long
data_size
,
void
*
data
)
{
return
efi_call_virt
(
set_variable
,
name
,
vendor
,
attr
,
data_size
,
data
);
unsigned
long
flags
;
efi_status_t
status
;
spin_lock_irqsave
(
&
efi_runtime_lock
,
flags
);
status
=
efi_call_virt
(
set_variable
,
name
,
vendor
,
attr
,
data_size
,
data
);
spin_unlock_irqrestore
(
&
efi_runtime_lock
,
flags
);
return
status
;
}
static
efi_status_t
virt_efi_set_variable_nonblocking
(
efi_char16_t
*
name
,
efi_guid_t
*
vendor
,
u32
attr
,
unsigned
long
data_size
,
void
*
data
)
{
unsigned
long
flags
;
efi_status_t
status
;
if
(
!
spin_trylock_irqsave
(
&
efi_runtime_lock
,
flags
))
return
EFI_NOT_READY
;
status
=
efi_call_virt
(
set_variable
,
name
,
vendor
,
attr
,
data_size
,
data
);
spin_unlock_irqrestore
(
&
efi_runtime_lock
,
flags
);
return
status
;
}
static
efi_status_t
virt_efi_query_variable_info
(
u32
attr
,
u64
*
storage_space
,
u64
*
remaining_space
,
u64
*
max_variable_size
)
{
unsigned
long
flags
;
efi_status_t
status
;
if
(
efi
.
runtime_version
<
EFI_2_00_SYSTEM_TABLE_REVISION
)
return
EFI_UNSUPPORTED
;
return
efi_call_virt
(
query_variable_info
,
attr
,
storage_space
,
spin_lock_irqsave
(
&
efi_runtime_lock
,
flags
);
status
=
efi_call_virt
(
query_variable_info
,
attr
,
storage_space
,
remaining_space
,
max_variable_size
);
spin_unlock_irqrestore
(
&
efi_runtime_lock
,
flags
);
return
status
;
}
static
efi_status_t
virt_efi_get_next_high_mono_count
(
u32
*
count
)
{
return
efi_call_virt
(
get_next_high_mono_count
,
count
);
unsigned
long
flags
;
efi_status_t
status
;
spin_lock_irqsave
(
&
efi_runtime_lock
,
flags
);
status
=
efi_call_virt
(
get_next_high_mono_count
,
count
);
spin_unlock_irqrestore
(
&
efi_runtime_lock
,
flags
);
return
status
;
}
static
void
virt_efi_reset_system
(
int
reset_type
,
...
...
@@ -119,17 +246,27 @@ static void virt_efi_reset_system(int reset_type,
unsigned
long
data_size
,
efi_char16_t
*
data
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
efi_runtime_lock
,
flags
);
__efi_call_virt
(
reset_system
,
reset_type
,
status
,
data_size
,
data
);
spin_unlock_irqrestore
(
&
efi_runtime_lock
,
flags
);
}
static
efi_status_t
virt_efi_update_capsule
(
efi_capsule_header_t
**
capsules
,
unsigned
long
count
,
unsigned
long
sg_list
)
{
unsigned
long
flags
;
efi_status_t
status
;
if
(
efi
.
runtime_version
<
EFI_2_00_SYSTEM_TABLE_REVISION
)
return
EFI_UNSUPPORTED
;
return
efi_call_virt
(
update_capsule
,
capsules
,
count
,
sg_list
);
spin_lock_irqsave
(
&
efi_runtime_lock
,
flags
);
status
=
efi_call_virt
(
update_capsule
,
capsules
,
count
,
sg_list
);
spin_unlock_irqrestore
(
&
efi_runtime_lock
,
flags
);
return
status
;
}
static
efi_status_t
virt_efi_query_capsule_caps
(
efi_capsule_header_t
**
capsules
,
...
...
@@ -137,11 +274,17 @@ static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
u64
*
max_size
,
int
*
reset_type
)
{
unsigned
long
flags
;
efi_status_t
status
;
if
(
efi
.
runtime_version
<
EFI_2_00_SYSTEM_TABLE_REVISION
)
return
EFI_UNSUPPORTED
;
return
efi_call_virt
(
query_capsule_caps
,
capsules
,
count
,
max_size
,
spin_lock_irqsave
(
&
efi_runtime_lock
,
flags
);
status
=
efi_call_virt
(
query_capsule_caps
,
capsules
,
count
,
max_size
,
reset_type
);
spin_unlock_irqrestore
(
&
efi_runtime_lock
,
flags
);
return
status
;
}
void
efi_native_runtime_setup
(
void
)
...
...
@@ -153,6 +296,7 @@ void efi_native_runtime_setup(void)
efi
.
get_variable
=
virt_efi_get_variable
;
efi
.
get_next_variable
=
virt_efi_get_next_variable
;
efi
.
set_variable
=
virt_efi_set_variable
;
efi
.
set_variable_nonblocking
=
virt_efi_set_variable_nonblocking
;
efi
.
get_next_high_mono_count
=
virt_efi_get_next_high_mono_count
;
efi
.
reset_system
=
virt_efi_reset_system
;
efi
.
query_variable_info
=
virt_efi_query_variable_info
;
...
...
drivers/firmware/efi/vars.c
浏览文件 @
75b12857
...
...
@@ -321,11 +321,11 @@ static unsigned long var_name_strnsize(efi_char16_t *variable_name,
* Print a warning when duplicate EFI variables are encountered and
* disable the sysfs workqueue since the firmware is buggy.
*/
static
void
dup_variable_bug
(
efi_char16_t
*
s16
,
efi_guid_t
*
vendor_guid
,
static
void
dup_variable_bug
(
efi_char16_t
*
s
tr
16
,
efi_guid_t
*
vendor_guid
,
unsigned
long
len16
)
{
size_t
i
,
len8
=
len16
/
sizeof
(
efi_char16_t
);
char
*
s8
;
char
*
s
tr
8
;
/*
* Disable the workqueue since the algorithm it uses for
...
...
@@ -334,16 +334,16 @@ static void dup_variable_bug(efi_char16_t *s16, efi_guid_t *vendor_guid,
*/
efivar_wq_enabled
=
false
;
s8
=
kzalloc
(
len8
,
GFP_KERNEL
);
if
(
!
s8
)
s
tr
8
=
kzalloc
(
len8
,
GFP_KERNEL
);
if
(
!
s
tr
8
)
return
;
for
(
i
=
0
;
i
<
len8
;
i
++
)
s
8
[
i
]
=
s
16
[
i
];
s
tr8
[
i
]
=
str
16
[
i
];
printk
(
KERN_WARNING
"efivars: duplicate variable: %s-%pUl
\n
"
,
s8
,
vendor_guid
);
kfree
(
s8
);
s
tr
8
,
vendor_guid
);
kfree
(
s
tr
8
);
}
/**
...
...
@@ -595,6 +595,39 @@ int efivar_entry_set(struct efivar_entry *entry, u32 attributes,
}
EXPORT_SYMBOL_GPL
(
efivar_entry_set
);
/*
* efivar_entry_set_nonblocking - call set_variable_nonblocking()
*
* This function is guaranteed to not block and is suitable for calling
* from crash/panic handlers.
*
* Crucially, this function will not block if it cannot acquire
* __efivars->lock. Instead, it returns -EBUSY.
*/
static
int
efivar_entry_set_nonblocking
(
efi_char16_t
*
name
,
efi_guid_t
vendor
,
u32
attributes
,
unsigned
long
size
,
void
*
data
)
{
const
struct
efivar_operations
*
ops
=
__efivars
->
ops
;
unsigned
long
flags
;
efi_status_t
status
;
if
(
!
spin_trylock_irqsave
(
&
__efivars
->
lock
,
flags
))
return
-
EBUSY
;
status
=
check_var_size
(
attributes
,
size
+
ucs2_strsize
(
name
,
1024
));
if
(
status
!=
EFI_SUCCESS
)
{
spin_unlock_irqrestore
(
&
__efivars
->
lock
,
flags
);
return
-
ENOSPC
;
}
status
=
ops
->
set_variable_nonblocking
(
name
,
&
vendor
,
attributes
,
size
,
data
);
spin_unlock_irqrestore
(
&
__efivars
->
lock
,
flags
);
return
efi_status_to_err
(
status
);
}
/**
* efivar_entry_set_safe - call set_variable() if enough space in firmware
* @name: buffer containing the variable name
...
...
@@ -622,6 +655,20 @@ int efivar_entry_set_safe(efi_char16_t *name, efi_guid_t vendor, u32 attributes,
if
(
!
ops
->
query_variable_store
)
return
-
ENOSYS
;
/*
* If the EFI variable backend provides a non-blocking
* ->set_variable() operation and we're in a context where we
* cannot block, then we need to use it to avoid live-locks,
* since the implication is that the regular ->set_variable()
* will block.
*
* If no ->set_variable_nonblocking() is provided then
* ->set_variable() is assumed to be non-blocking.
*/
if
(
!
block
&&
ops
->
set_variable_nonblocking
)
return
efivar_entry_set_nonblocking
(
name
,
vendor
,
attributes
,
size
,
data
);
if
(
!
block
)
{
if
(
!
spin_trylock_irqsave
(
&
__efivars
->
lock
,
flags
))
return
-
EBUSY
;
...
...
drivers/rtc/Kconfig
浏览文件 @
75b12857
...
...
@@ -806,7 +806,7 @@ config RTC_DRV_DA9063
config RTC_DRV_EFI
tristate "EFI RTC"
depends on EFI
depends on EFI
&& !X86
help
If you say yes here you will get support for the EFI
Real Time Clock.
...
...
drivers/rtc/rtc-efi.c
浏览文件 @
75b12857
...
...
@@ -236,3 +236,4 @@ MODULE_ALIAS("platform:rtc-efi");
MODULE_AUTHOR
(
"dann frazier <dannf@hp.com>"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_DESCRIPTION
(
"EFI RTC driver"
);
MODULE_ALIAS
(
"platform:rtc-efi"
);
include/linux/efi.h
浏览文件 @
75b12857
...
...
@@ -92,6 +92,7 @@ typedef struct {
#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL)
/* write-coalescing */
#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL)
/* write-through */
#define EFI_MEMORY_WB ((u64)0x0000000000000008ULL)
/* write-back */
#define EFI_MEMORY_UCE ((u64)0x0000000000000010ULL)
/* uncached, exported */
#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL)
/* write-protect */
#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL)
/* read-protect */
#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL)
/* execute-protect */
...
...
@@ -502,6 +503,10 @@ typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char
typedef
efi_status_t
efi_set_variable_t
(
efi_char16_t
*
name
,
efi_guid_t
*
vendor
,
u32
attr
,
unsigned
long
data_size
,
void
*
data
);
typedef
efi_status_t
efi_set_variable_nonblocking_t
(
efi_char16_t
*
name
,
efi_guid_t
*
vendor
,
u32
attr
,
unsigned
long
data_size
,
void
*
data
);
typedef
efi_status_t
efi_get_next_high_mono_count_t
(
u32
*
count
);
typedef
void
efi_reset_system_t
(
int
reset_type
,
efi_status_t
status
,
unsigned
long
data_size
,
efi_char16_t
*
data
);
...
...
@@ -821,6 +826,7 @@ extern struct efi {
efi_get_variable_t
*
get_variable
;
efi_get_next_variable_t
*
get_next_variable
;
efi_set_variable_t
*
set_variable
;
efi_set_variable_nonblocking_t
*
set_variable_nonblocking
;
efi_query_variable_info_t
*
query_variable_info
;
efi_update_capsule_t
*
update_capsule
;
efi_query_capsule_caps_t
*
query_capsule_caps
;
...
...
@@ -886,6 +892,13 @@ extern bool efi_poweroff_required(void);
(md) <= (efi_memory_desc_t *)((m)->map_end - (m)->desc_size); \
(md) = (void *)(md) + (m)->desc_size)
/*
* Format an EFI memory descriptor's type and attributes to a user-provided
* character buffer, as per snprintf(), and return the buffer.
*/
char
*
__init
efi_md_typeattr_format
(
char
*
buf
,
size_t
size
,
const
efi_memory_desc_t
*
md
);
/**
* efi_range_is_wc - check the WC bit on an address range
* @start: starting kvirt address
...
...
@@ -1034,6 +1047,7 @@ struct efivar_operations {
efi_get_variable_t
*
get_variable
;
efi_get_next_variable_t
*
get_next_variable
;
efi_set_variable_t
*
set_variable
;
efi_set_variable_nonblocking_t
*
set_variable_nonblocking
;
efi_query_variable_store_t
*
query_variable_store
;
};
...
...
@@ -1227,4 +1241,7 @@ efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg,
unsigned
long
*
load_addr
,
unsigned
long
*
load_size
);
efi_status_t
efi_parse_options
(
char
*
cmdline
);
bool
efi_runtime_disabled
(
void
);
#endif
/* _LINUX_EFI_H */
include/linux/kernel.h
浏览文件 @
75b12857
...
...
@@ -407,6 +407,7 @@ int vsscanf(const char *, const char *, va_list);
extern
int
get_option
(
char
**
str
,
int
*
pint
);
extern
char
*
get_options
(
const
char
*
str
,
int
nints
,
int
*
ints
);
extern
unsigned
long
long
memparse
(
const
char
*
ptr
,
char
**
retptr
);
extern
bool
parse_option_str
(
const
char
*
str
,
const
char
*
option
);
extern
int
core_kernel_text
(
unsigned
long
addr
);
extern
int
core_kernel_data
(
unsigned
long
addr
);
...
...
lib/cmdline.c
浏览文件 @
75b12857
...
...
@@ -160,3 +160,32 @@ unsigned long long memparse(const char *ptr, char **retptr)
return
ret
;
}
EXPORT_SYMBOL
(
memparse
);
/**
* parse_option_str - Parse a string and check an option is set or not
* @str: String to be parsed
* @option: option name
*
* This function parses a string containing a comma-separated list of
* strings like a=b,c.
*
* Return true if there's such option in the string, or return false.
*/
bool
parse_option_str
(
const
char
*
str
,
const
char
*
option
)
{
while
(
*
str
)
{
if
(
!
strncmp
(
str
,
option
,
strlen
(
option
)))
{
str
+=
strlen
(
option
);
if
(
!*
str
||
*
str
==
','
)
return
true
;
}
while
(
*
str
&&
*
str
!=
','
)
str
++
;
if
(
*
str
==
','
)
str
++
;
}
return
false
;
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录