Changeset View
Standalone View
sys/dev/efidev/efirt.c
Show All 28 Lines | |||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/efi.h> | #include <sys/efi.h> | ||||
#include <sys/eventhandler.h> | #include <sys/eventhandler.h> | ||||
kib: Please order includes alphabetically. sys/uio.h goes right before sys/vmmeter.h | |||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/linker.h> | #include <sys/linker.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/malloc.h> | |||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
Not Done Inline Actionsmalloc.h is before module.h kib: malloc.h is before module.h | |||||
#include <sys/clock.h> | #include <sys/clock.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/reboot.h> | #include <sys/reboot.h> | ||||
#include <sys/rwlock.h> | #include <sys/rwlock.h> | ||||
#include <sys/sched.h> | #include <sys/sched.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/uio.h> | |||||
#include <sys/vmmeter.h> | #include <sys/vmmeter.h> | ||||
#include <machine/fpu.h> | #include <machine/fpu.h> | ||||
#include <machine/efi.h> | #include <machine/efi.h> | ||||
#include <machine/metadata.h> | #include <machine/metadata.h> | ||||
#include <machine/vmparam.h> | #include <machine/vmparam.h> | ||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
#include <vm/vm_map.h> | #include <vm/vm_map.h> | ||||
static struct efi_systbl *efi_systbl; | static struct efi_systbl *efi_systbl; | ||||
static eventhandler_tag efi_shutdown_tag; | static eventhandler_tag efi_shutdown_tag; | ||||
Not Done Inline Actionswe have nitems() macro, please use it and not this hand-made one kib: we have nitems() macro, please use it and not this hand-made one | |||||
/* | /* | ||||
* The following pointers point to tables in the EFI runtime service data pages. | * The following pointers point to tables in the EFI runtime service data pages. | ||||
* Care should be taken to make sure that we've properly entered the EFI runtime | * Care should be taken to make sure that we've properly entered the EFI runtime | ||||
* environment (efi_enter()) before dereferencing them. | * environment (efi_enter()) before dereferencing them. | ||||
*/ | */ | ||||
static struct efi_cfgtbl *efi_cfgtbl; | static struct efi_cfgtbl *efi_cfgtbl; | ||||
static struct efi_rt *efi_runtime; | static struct efi_rt *efi_runtime; | ||||
Show All 20 Lines | static int efi_status2err[25] = { | ||||
EDOOFUS, /* EFI_NOT_STARTED */ | EDOOFUS, /* EFI_NOT_STARTED */ | ||||
EALREADY, /* EFI_ALREADY_STARTED */ | EALREADY, /* EFI_ALREADY_STARTED */ | ||||
ECANCELED, /* EFI_ABORTED */ | ECANCELED, /* EFI_ABORTED */ | ||||
EPROTO, /* EFI_ICMP_ERROR */ | EPROTO, /* EFI_ICMP_ERROR */ | ||||
EPROTO, /* EFI_TFTP_ERROR */ | EPROTO, /* EFI_TFTP_ERROR */ | ||||
EPROTO /* EFI_PROTOCOL_ERROR */ | EPROTO /* EFI_PROTOCOL_ERROR */ | ||||
}; | }; | ||||
enum efi_table_type { | |||||
TYPE_ESRT = 0, | |||||
TYPE_PROP | |||||
}; | |||||
static int efi_enter(void); | static int efi_enter(void); | ||||
static void efi_leave(void); | static void efi_leave(void); | ||||
int | int | ||||
efi_status_to_errno(efi_status status) | efi_status_to_errno(efi_status status) | ||||
{ | { | ||||
u_long code; | u_long code; | ||||
▲ Show 20 Lines • Show All 224 Lines • ▼ Show 20 Lines | while (count--) { | ||||
} | } | ||||
ct++; | ct++; | ||||
} | } | ||||
efi_leave(); | efi_leave(); | ||||
return (ENOENT); | return (ENOENT); | ||||
} | } | ||||
static int | |||||
get_table_length(enum efi_table_type type, size_t *table_len, void **taddr) | |||||
{ | |||||
switch (type) { | |||||
case TYPE_ESRT: | |||||
{ | |||||
Not Done Inline ActionsUnindent this '{' by one tab and correspondingly all lines under its scope. kib: Unindent this '{' by one tab and correspondingly all lines under its scope. | |||||
struct efi_esrt_table *esrt = NULL; | |||||
struct uuid uuid = EFI_TABLE_ESRT; | |||||
uint32_t fw_resource_count = 0; | |||||
size_t len = sizeof(*esrt); | |||||
int error; | |||||
void *buf; | |||||
Not Done Inline ActionsStyle discourages initialization in declaration, and we certainly do not do complex initialization (like calling malloc(9)) in declaration. kib: Style discourages initialization in declaration, and we certainly do not do complex… | |||||
error = efi_get_table(&uuid, (void **)&esrt); | |||||
if (error != 0) { | |||||
return (error); | |||||
} | |||||
Not Done Inline ActionsThis break results in returning ENOENT on case of efi_get_table() error. I do not think it is right, the original error should be returned. kib: This break results in returning ENOENT on case of efi_get_table() error. I do not think it is… | |||||
buf = malloc(len, M_TEMP, M_WAITOK); | |||||
error = physcopyout((vm_paddr_t)esrt, buf, len); | |||||
if (error != 0) { | |||||
free(buf, M_TEMP); | |||||
return (error); | |||||
Not Done Inline ActionsSame note about error. kib: Same note about error. | |||||
} | |||||
/* Check ESRT version */ | |||||
Not Done Inline ActionsTry to add D30785 to your test setup. I think this is the problem. kib: Try to add D30785 to your test setup. I think this is the problem. | |||||
Done Inline ActionsThanks, this this patch all works as expected! pavel.balaev_3mdeb.com: Thanks, this this patch all works as expected! | |||||
Not Done Inline ActionsOk, the physcopyin() fix landed into HEAD. You can finish polishing the patch. kib: Ok, the physcopyin() fix landed into HEAD. You can finish polishing the patch. | |||||
if (((struct efi_esrt_table *)buf)->fw_resource_version != | |||||
ESRT_FIRMWARE_RESOURCE_VERSION) { | |||||
Not Done Inline Actionsindent kib: indent | |||||
kibUnsubmitted Not Done Inline ActionsIndent should be +4 spaces for the continuation line. kib: Indent should be +4 spaces for the continuation line. | |||||
return (ENODEV); | |||||
Not Done Inline ActionsAFAIR ENXIO is also returned if EFI RT services are not available. I do not think that userspace can practically distinguish between cases, perhaps a different error value would be more useful. kib: AFAIR ENXIO is also returned if EFI RT services are not available. I do not think that… | |||||
kibUnsubmitted Not Done Inline ActionsShould do free(buf) there? kib: Should do free(buf) there? | |||||
} | |||||
fw_resource_count = ((struct efi_esrt_table *)buf)->fw_resource_count; | |||||
Done Inline ActionsThese are structures definitions as provided by UEFI spec, right? kib: These are structures definitions as provided by UEFI spec, right?
I suggest to put them e.g. | |||||
Done Inline ActionsYes, from spec. Got it. pavel.balaev_3mdeb.com: Yes, from spec. Got it. | |||||
len += sizeof(struct efi_esrt_entry_v1) * fw_resource_count; | |||||
kibUnsubmitted Not Done Inline ActionsIn principle, it would be nice to check the mul operation for overflow. Also in principle, it would be nice to put some arbitrary limit there, so that we do not try to malloc() excessively large kernel memory later, kernel really does not tolerate such attemtps. This is mostly to have some minimal protection against buggy bioses. kib: In principle, it would be nice to check the mul operation for overflow. Also in principle, it… | |||||
*table_len = len; | |||||
if (taddr != NULL) { | |||||
*taddr = esrt; | |||||
Not Done Inline ActionsNo, please do not bring linuxkpi to native freebsd code. Checking for overflow is good but not enough, kernel cannot handle even much smaller sizes for overgrown alloc requests. Put some reasonable limit there, say 128K sounds good and arbitrary. If you worry that it might be too limiting, add sysctl that manages the limit. kib: No, please do not bring linuxkpi to native freebsd code. Checking for overflow is good but not… | |||||
Done Inline ActionsOK, so I can only use arbitrary limits without overflow check, or use limit with different overflow check mechanism? pavel.balaev_3mdeb.com: OK, so I can only use arbitrary limits without overflow check, or use limit with different… | |||||
Not Done Inline ActionsIt is easy to combine overflow and limit checks into one condition, using standard C: #define EFI_TABLE_ALLOC_MAX (128 * 1024 * 1024) if (fw_resource_count > EFI_TABLE_ALLOC_MAX / sizeof(struct efi_esrt_entry_v1)) { free(buf, M_TEMP); return (ENODEV); /* Not sure that this error code is best, but ok */ } kib: It is easy to combine overflow and limit checks into one condition, using standard C:
```… | |||||
} | |||||
free(buf, M_TEMP); | |||||
return (0); | |||||
} | |||||
case TYPE_PROP: | |||||
Not Done Inline ActionsThis should be like this kib: This should be like this
`esrt_ptr = (struct esrt_table *)efi_phys_to_kv((vm_paddr_t)ptr);` | |||||
Not Done Inline Actionsok. pavel.balaev_3mdeb.com: ok. | |||||
{ | |||||
struct uuid uuid = EFI_PROPERTIES_TABLE; | |||||
struct efi_prop_table *prop; | |||||
Not Done Inline Actionsif (esrt_ptr == NULL || ... kib: `if (esrt_ptr == NULL || ...` | |||||
size_t len = sizeof(*prop); | |||||
uint32_t prop_len; | |||||
int error; | |||||
void *buf; | |||||
error = efi_get_table(&uuid, (void **)&prop); | |||||
Not Done Inline ActionsSo the big question: Should we do the same there? kib: So the big question:
why did you decided to parse the table in kernel, and provided the parsed… | |||||
Done Inline ActionsOK, this is good idea. I will rework the patch. Resubmit it in this review, or create new? pavel.balaev_3mdeb.com: OK, this is good idea. I will rework the patch. Resubmit it in this review, or create new? | |||||
Not Done Inline ActionsBetter to continue with this review, so that the whole history of the patch is kept in single place. kib: Better to continue with this review, so that the whole history of the patch is kept in single… | |||||
Done Inline ActionsDo you mean that we should parse ESRT table from user-space tool? pavel.balaev_3mdeb.com: Do you mean that we should parse ESRT table from user-space tool?
F.e. Linux parse it in kernel… | |||||
Not Done Inline ActionsWhat is the advantage of parsing this table in kernel? Do you (or somebody else) plan to have a consumer for this table in kernel? If not, then why adding more code to kernel, which should deal with not very trusted source? If there are uses of it in kernel, we should think how to represent it internally, and only then select the external representation. Per-entry sysctl is really not how sysctls should be used. kib: What is the advantage of parsing this table in kernel? Do you (or somebody else) plan to have… | |||||
Done Inline ActionsNo consumers in kernel planned. So I agree that my solution is wrong. else if (strcmp(fmt, "S,efi_esrt) == 0) func = S_efi_esrt; something like this? pavel.balaev_3mdeb.com: No consumers in kernel planned. So I agree that my solution is wrong.
So I need to push blob… | |||||
Not Done Inline ActionsI am not even sure that sysctl(2)/sysctl(8) is the right tool to use there. I just had a flash-back. We have efidev(4) AKA /dev/efi, which provided (broken) EFIIOC_GET_TABLE ioctl. I think the right route there is to resurrect the ioctl, perhaps fixing it e.g. to actually work and eliminate the need to use KVA access. For instance, it might take the pointer to userspace buffer where to copy-out the requested EFI table. Then we need a userspace tool that would use the ioctl to fetch some table, parse it, and provide the usable representation of data e.g. for scripts and for humans. I do not think that we have a tool that can be logically extended, so a new utility might be a reasonable proposition. kib: I am not even sure that sysctl(2)/sysctl(8) is the right tool to use there. I just had a flash… | |||||
Done Inline ActionsOK got it, but have one question: pavel.balaev_3mdeb.com: OK got it, but have one question:
I don't get how to eliminate KVA access, so for example… | |||||
Done Inline ActionsI can phys_to_kva, then parse data in kernel space into buffer, then copy it to user. This is simple, but I think it is wrong. pavel.balaev_3mdeb.com: I can phys_to_kva, then parse data in kernel space into buffer, then copy it to user. This is… | |||||
Done Inline ActionsGot it, I can just use cast (vm_paddr_t)ptr, I will resurrect this syscall, and see why it not works and try to fix it. pavel.balaev_3mdeb.com: Got it, I can just use cast (vm_paddr_t)ptr, I will resurrect this syscall, and see why it not… | |||||
Not Done Inline ActionsSorry I was not clear enough. To see what I mean by 'eliminating access to KVA' you need to see the original (removed) ioctl GET_TABLE interface. It returned some address for the table to userspace, and then userspace needs to access /dev/mem to fetch the actual table data. Sane ioctl interface would take a pointer to userspace buffer and copyout the table to buffer, eliminating any /dev/mem activities. Sure, the kernel side would need to allocate some bounce buffer, enter EFIRT mapping mode, copy to the buffer, then exit EFIRT and copyout the buffer to userspace. kib: Sorry I was not clear enough. To see what I mean by 'eliminating access to KVA' you need to… | |||||
Done Inline ActionsThanks, will try to create sane ioctl interface. pavel.balaev_3mdeb.com: Thanks, will try to create sane ioctl interface. | |||||
Done Inline Actions
Do you mean efi_enter()/efi_leave(), and is a any way to get partition table size? pavel.balaev_3mdeb.com: > enter EFIRT mapping mode
Do you mean efi_enter()/efi_leave(), and is a any way to get… | |||||
Done Inline ActionsI mean that we can access to table data: pavel.balaev_3mdeb.com: I mean that we can access to table data:
efi_enter();
struct efi_cfgtbl *ct;
ct->ct_data… | |||||
Not Done Inline ActionsI do not quite understand what do you mean by 'partition size'. I will answer two other questions instead, in the hope that one of them is actually what you intended to ask. First, userspace ioctl interface should provide the size of the incoming buffer for kernel to copy out the table. Userspace cannot know in advance how large the buffer should be. Typical interface is designed to return the actual copied length alongside the data, but passing a NULL pointer for the buffer results in returning the total length needed. See for instance sysctl(2). So if, for instance, ioctl takes the following structure struct efi_esrt_io { void *buf; /* in, pointer to buffer */ size_t buf_len; /* in, size of the buffer */ size_t filled_len; /* out, how much of the buffer is filled */ }; and setting buf = NULL would provide the filled_len of the required buf size. Second, the length of the table is stored in the table itself, you need to copy FwResourceCount EFI_SYSTEM_RESOURCE_ENTRYies. Yes, you can read the counter after efi_enter(), then do efi_leave(), allocate the memory, then do efi_enter() again and copy to that temporal buffer, then efi_leave() again. Now you can copy out to userspace and free the buffer. kib: I do not quite understand what do you mean by 'partition size'. I will answer two other… | |||||
Done Inline ActionsThanks for the answer, about userspace ioctl interface it's all clear. The last question is: can I dereference struct efi_cfgtbl *ct; ct->ct_data after efi_enter() without using efi_phys_to_kva() ? pavel.balaev_3mdeb.com: Thanks for the answer, about userspace ioctl interface it's all clear.
I mean that if I get… | |||||
Not Done Inline ActionsYes, and yes. Your implementation should be aware of the table' type and the way to calculate the length for specific table type. I would be more certain about some design decisions and interfaces if you handle ESRT and one more table, does not matter which. Only to avoid making the generalization from one data point. kib: Yes, and yes. Your implementation should be aware of the table' type and the way to calculate… | |||||
Done Inline ActionsThanks! I will try to find one more sutable table to add. pavel.balaev_3mdeb.com: Thanks! I will try to find one more sutable table to add. | |||||
Not Done Inline ActionsI looked at the EFI spec 4.6 EFI_CONFIGURATION_TABLE definition, and I see that they require void *VendorTable to be the physical address, not EFIRT remapped address. So you do not need efi_enter()/leave() at all and can directly access the physical addresses instead. uiomove_fromphys(9) should do it. kib: I looked at the EFI spec 4.6 EFI_CONFIGURATION_TABLE definition, and I see that they require… | |||||
Done Inline ActionsThis is valid only for copying? for get_length() I should use efi_enter() anyway? pavel.balaev_3mdeb.com: This is valid only for copying? for get_length() I should use efi_enter() anyway? | |||||
Not Done Inline ActionsFormally efi_enter() is not valid, if we ever switch from 1:1 EFIRT memory mapping to something more involved. BTW, you can use uiomove_fromphys() with UIO_SYSSPACE to the header. kib: Formally efi_enter() is not valid, if we ever switch from 1:1 EFIRT memory mapping to something… | |||||
Done Inline ActionsI've got this results: this works fine: efi_get_table(&uuid, (void **)&esrt); efi_enter(); fw_resource_count = esrt->fw_resource_count; efi_leave(); panic: page fault: efi_get_table(&uuid, (void **)&esrt); fw_resource_count = esrt->fw_resource_count; unexpected data: (maybe I use this function wrong) void *buf = malloc(len, M_TEMP, M_WAITOK); efi_get_table(&uuid, (void **)&esrt); physcopyout((vm_paddr_t)esrt, buf, len); fw_resource_count = ((struct efi_esrt_table *)buf)->fw_resource_count; pavel.balaev_3mdeb.com: I've got this results:
this works fine:
```
efi_get_table(&uuid, (void **)&esrt);
efi_enter()… | |||||
Not Done Inline ActionsSecond snippet faulted because you tried to deferefence a pointer belonging to the physical address space. Kernel is executing in Kernel Virtual Address space, so it cannot do it this way. Third snippedt is wrong because you did physcopyout() overwriting the table instead of physcopyin(), copying from table to your buffer. WIth that detail fixed, I hope this would work and this is the best way to get to the table. kib: Second snippet faulted because you tried to deferefence a pointer belonging to the physical… | |||||
Done Inline ActionsAre you sure about about physcopyin() ? and physcopyout(vm_paddr_t src, void *dst, size_t len) pavel.balaev_3mdeb.com: Are you sure about about physcopyin() ?
it has input args: physcopyin(void *src, vm_paddr_t… | |||||
Done Inline Actionsafter debugging physcopyout((vm_paddr_t)esrt, buf, len); define bcopy(a,b,c) memmove(b,a,c) so physcopyout() copy data from phys to iov_base but data is wrong pavel.balaev_3mdeb.com: after debugging physcopyout((vm_paddr_t)esrt, buf, len);
I see:
get_table_length: esrt… | |||||
Done Inline ActionsEven from userspace a can mmap /dev/mem with offset=0xac25d598 and get actual data. pavel.balaev_3mdeb.com: Even from userspace a can mmap /dev/mem with offset=0xac25d598 and get actual data.
I dont get… | |||||
Not Done Inline ActionsCan you push the current patch as is (non-working)? I will read it as a whole. The bcopy line above looks somewhat stange. The source address for bcopy is 0xfffff80000000598. The direct map starts at 0xfffff80000000000, so basically you are reading from the physical address 0x598, which is unlikely to contain a UEFI table. What is the phys address for the ESRT table that is given to you? kib: Can you push the current patch as is (non-working)? I will read it as a whole.
I think you are… | |||||
Done Inline Actionsphys address of esrt table is: 0xac25d598. pavel.balaev_3mdeb.com: phys address of esrt table is: 0xac25d598. | |||||
Done Inline Actionsnew patch pushed pavel.balaev_3mdeb.com: new patch pushed | |||||
Done Inline ActionsAnd second table will be EFI_DEBUG_IMAGE_INFO_TABLE. Is it OK? pavel.balaev_3mdeb.com: And second table will be EFI_DEBUG_IMAGE_INFO_TABLE. Is it OK? | |||||
Done Inline ActionsEFI_PROPERTIES_TABLE_GUID will be simpler. pavel.balaev_3mdeb.com: EFI_PROPERTIES_TABLE_GUID will be simpler. | |||||
Not Done Inline ActionsOk, although not very useful. kib: Ok, although not very useful. | |||||
if (error != 0) { | |||||
return (error); | |||||
} | |||||
buf = malloc(len, M_TEMP, M_WAITOK); | |||||
error = physcopyout((vm_paddr_t)prop, buf, len); | |||||
if (error != 0) { | |||||
free(buf, M_TEMP); | |||||
return (error); | |||||
} | |||||
prop_len = ((struct efi_prop_table *)buf)->length; | |||||
kibUnsubmitted Not Done Inline ActionsAgain, add some arbitrary limit? kib: Again, add some arbitrary limit? | |||||
*table_len = prop_len; | |||||
if (taddr != NULL) { | |||||
*taddr = prop; | |||||
} | |||||
return (0); | |||||
} | |||||
} | |||||
return (ENOENT); | |||||
} | |||||
static int | |||||
copy_table(struct uuid *uuid, void **buf, size_t buf_len, size_t *table_len) | |||||
{ | |||||
static const struct known_table { | |||||
struct uuid uuid; | |||||
enum efi_table_type type; | |||||
} tables[] = { | |||||
{ EFI_TABLE_ESRT, TYPE_ESRT }, | |||||
{ EFI_PROPERTIES_TABLE, TYPE_PROP } | |||||
Not Done Inline Actionsstatic const struct ... BTW if you insist on defining known_table scoped in the function, you can do something like static const struct known_table{...} tables[] = {...}; kib: `static const struct ...`
BTW if you insist on defining known_table scoped in the function… | |||||
}; | |||||
size_t table_idx; | |||||
void *taddr; | |||||
int rc; | |||||
for (table_idx = 0; table_idx < nitems(tables); table_idx++) { | |||||
if (!bcmp(&tables[table_idx].uuid, uuid, sizeof(*uuid))) { | |||||
break; | |||||
} | |||||
} | |||||
if (table_idx == nitems(tables)) { | |||||
return (EINVAL); | |||||
} | |||||
rc = get_table_length(tables[table_idx].type, table_len, &taddr); | |||||
Not Done Inline ActionsRemove table_supported variable, and change the condition to table_idx == nitems(tables). kib: Remove table_supported variable, and change the condition to `table_idx == nitems(tables)`. | |||||
if (rc != 0) { | |||||
return rc; | |||||
} | |||||
/* return table length to userspace */ | |||||
if (buf == NULL) { | |||||
return (0); | |||||
} | |||||
*buf = malloc(*table_len, M_TEMP, M_WAITOK); | |||||
if (*buf == NULL) { | |||||
return (ENOMEM); | |||||
} | |||||
rc = physcopyout((vm_paddr_t)taddr, *buf, *table_len); | |||||
return (rc); | |||||
} | |||||
static int efi_rt_handle_faults = EFI_RT_HANDLE_FAULTS_DEFAULT; | static int efi_rt_handle_faults = EFI_RT_HANDLE_FAULTS_DEFAULT; | ||||
SYSCTL_INT(_machdep, OID_AUTO, efi_rt_handle_faults, CTLFLAG_RWTUN, | SYSCTL_INT(_machdep, OID_AUTO, efi_rt_handle_faults, CTLFLAG_RWTUN, | ||||
&efi_rt_handle_faults, 0, | &efi_rt_handle_faults, 0, | ||||
"Call EFI RT methods with fault handler wrapper around"); | "Call EFI RT methods with fault handler wrapper around"); | ||||
static int | static int | ||||
efi_rt_arch_call_nofault(struct efirt_callinfo *ec) | efi_rt_arch_call_nofault(struct efirt_callinfo *ec) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 216 Lines • ▼ Show 20 Lines | var_set(efi_char *name, struct uuid *vendor, uint32_t attrib, | ||||
ec.ec_arg5 = (uintptr_t)data; | ec.ec_arg5 = (uintptr_t)data; | ||||
ec.ec_fptr = EFI_RT_METHOD_PA(rt_setvar); | ec.ec_fptr = EFI_RT_METHOD_PA(rt_setvar); | ||||
return (efi_call(&ec)); | return (efi_call(&ec)); | ||||
} | } | ||||
const static struct efi_ops efi_ops = { | const static struct efi_ops efi_ops = { | ||||
.rt_ok = rt_ok, | .rt_ok = rt_ok, | ||||
.get_table = get_table, | .get_table = get_table, | ||||
.copy_table = copy_table, | |||||
.get_time = get_time, | .get_time = get_time, | ||||
.get_time_capabilities = get_time_capabilities, | .get_time_capabilities = get_time_capabilities, | ||||
.reset_system = reset_system, | .reset_system = reset_system, | ||||
.set_time = set_time, | .set_time = set_time, | ||||
.var_get = var_get, | .var_get = var_get, | ||||
.var_nextname = var_nextname, | .var_nextname = var_nextname, | ||||
.var_set = var_set, | .var_set = var_set, | ||||
}; | }; | ||||
Show All 30 Lines |
Please order includes alphabetically. sys/uio.h goes right before sys/vmmeter.h