Skip to content
Snippets Groups Projects
Commit f6dd3f35 authored by Heinrich Schuchardt's avatar Heinrich Schuchardt Committed by Alexander Graf
Browse files

efi_loader: correcty determine total device path length


Device paths may consist of multiple instances. Up to now we have only
considered the size of the first instance. For the services of the
EFI_DEVICE_PATH_UTILITIES_PROTOCOL in most cases the total length of the
device path is relevant.

So let's rename efi_dp_size() to efi_dp_instance_size() and create a new
function efi_dp_size() that calculates the total device path length.

Signed-off-by: default avatarHeinrich Schuchardt <xypron.glpk@gmx.de>
Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
parent adb57512
No related branches found
No related tags found
No related merge requests found
...@@ -324,7 +324,10 @@ int efi_dp_match(const struct efi_device_path *a, ...@@ -324,7 +324,10 @@ int efi_dp_match(const struct efi_device_path *a,
const struct efi_device_path *b); const struct efi_device_path *b);
struct efi_object *efi_dp_find_obj(struct efi_device_path *dp, struct efi_object *efi_dp_find_obj(struct efi_device_path *dp,
struct efi_device_path **rem); struct efi_device_path **rem);
unsigned efi_dp_size(const struct efi_device_path *dp); /* get size of the first device path instance excluding end node */
efi_uintn_t efi_dp_instance_size(const struct efi_device_path *dp);
/* size of multi-instance device path excluding end node */
efi_uintn_t efi_dp_size(const struct efi_device_path *dp);
struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp); struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp);
struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1, struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
const struct efi_device_path *dp2); const struct efi_device_path *dp2);
......
...@@ -2219,7 +2219,7 @@ static efi_status_t EFIAPI efi_locate_device_path( ...@@ -2219,7 +2219,7 @@ static efi_status_t EFIAPI efi_locate_device_path(
} }
/* Find end of device path */ /* Find end of device path */
len = efi_dp_size(*device_path); len = efi_dp_instance_size(*device_path);
/* Get all handles implementing the protocol */ /* Get all handles implementing the protocol */
ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, protocol, NULL, ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, protocol, NULL,
...@@ -2234,7 +2234,7 @@ static efi_status_t EFIAPI efi_locate_device_path( ...@@ -2234,7 +2234,7 @@ static efi_status_t EFIAPI efi_locate_device_path(
if (ret != EFI_SUCCESS) if (ret != EFI_SUCCESS)
continue; continue;
dp = (struct efi_device_path *)handler->protocol_interface; dp = (struct efi_device_path *)handler->protocol_interface;
len_dp = efi_dp_size(dp); len_dp = efi_dp_instance_size(dp);
/* /*
* This handle can only be a better fit * This handle can only be a better fit
* if its device path length is longer than the best fit and * if its device path length is longer than the best fit and
......
...@@ -149,7 +149,7 @@ static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path, ...@@ -149,7 +149,7 @@ static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path,
struct efi_device_path **rem) struct efi_device_path **rem)
{ {
struct efi_object *efiobj; struct efi_object *efiobj;
unsigned int dp_size = efi_dp_size(dp); efi_uintn_t dp_size = efi_dp_instance_size(dp);
list_for_each_entry(efiobj, &efi_obj_list, link) { list_for_each_entry(efiobj, &efi_obj_list, link) {
struct efi_handler *handler; struct efi_handler *handler;
...@@ -170,11 +170,12 @@ static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path, ...@@ -170,11 +170,12 @@ static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path,
* the caller. * the caller.
*/ */
*rem = ((void *)dp) + *rem = ((void *)dp) +
efi_dp_size(obj_dp); efi_dp_instance_size(obj_dp);
return efiobj; return efiobj;
} else { } else {
/* Only return on exact matches */ /* Only return on exact matches */
if (efi_dp_size(obj_dp) == dp_size) if (efi_dp_instance_size(obj_dp) ==
dp_size)
return efiobj; return efiobj;
} }
} }
...@@ -229,10 +230,10 @@ const struct efi_device_path *efi_dp_last_node(const struct efi_device_path *dp) ...@@ -229,10 +230,10 @@ const struct efi_device_path *efi_dp_last_node(const struct efi_device_path *dp)
return ret; return ret;
} }
/* return size not including End node: */ /* get size of the first device path instance excluding end node */
unsigned efi_dp_size(const struct efi_device_path *dp) efi_uintn_t efi_dp_instance_size(const struct efi_device_path *dp)
{ {
unsigned sz = 0; efi_uintn_t sz = 0;
if (!dp || dp->type == DEVICE_PATH_TYPE_END) if (!dp || dp->type == DEVICE_PATH_TYPE_END)
return 0; return 0;
...@@ -244,10 +245,25 @@ unsigned efi_dp_size(const struct efi_device_path *dp) ...@@ -244,10 +245,25 @@ unsigned efi_dp_size(const struct efi_device_path *dp)
return sz; return sz;
} }
/* get size of multi-instance device path excluding end node */
efi_uintn_t efi_dp_size(const struct efi_device_path *dp)
{
const struct efi_device_path *p = dp;
if (!p)
return 0;
while (p->type != DEVICE_PATH_TYPE_END ||
p->sub_type != DEVICE_PATH_SUB_TYPE_END)
p = (void *)p + p->length;
return (void *)p - (void *)dp;
}
/* copy multi-instance device path */
struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp) struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp)
{ {
struct efi_device_path *ndp; struct efi_device_path *ndp;
unsigned sz = efi_dp_size(dp) + sizeof(END); size_t sz = efi_dp_size(dp) + sizeof(END);
if (!dp) if (!dp)
return NULL; return NULL;
...@@ -298,7 +314,7 @@ struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, ...@@ -298,7 +314,7 @@ struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
} else if (!node) { } else if (!node) {
ret = efi_dp_dup(dp); ret = efi_dp_dup(dp);
} else if (!dp) { } else if (!dp) {
unsigned sz = node->length; size_t sz = node->length;
void *p = dp_alloc(sz + sizeof(END)); void *p = dp_alloc(sz + sizeof(END));
if (!p) if (!p)
return NULL; return NULL;
...@@ -307,7 +323,7 @@ struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, ...@@ -307,7 +323,7 @@ struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
ret = p; ret = p;
} else { } else {
/* both dp and node are non-null */ /* both dp and node are non-null */
unsigned sz = efi_dp_size(dp); size_t sz = efi_dp_size(dp);
void *p = dp_alloc(sz + node->length + sizeof(END)); void *p = dp_alloc(sz + node->length + sizeof(END));
if (!p) if (!p)
return NULL; return NULL;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment