mirror of
https://github.com/u-boot/u-boot.git
synced 2025-05-08 19:11:53 +00:00
efi: hii: add keyboard layout package support
Allow for handling keyboard layout package in HII database protocol. A package can be added or deleted in HII database protocol, but we don't set 'current' keyboard layout as there is no driver that requests a keyboard layout. Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org> Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
9ab0bdd9fe
commit
8d3b77e36e
2 changed files with 148 additions and 5 deletions
|
@ -845,6 +845,12 @@ struct efi_hii_keyboard_layout {
|
||||||
struct efi_key_descriptor descriptors[];
|
struct efi_key_descriptor descriptors[];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
struct efi_hii_keyboard_package {
|
||||||
|
struct efi_hii_package_header header;
|
||||||
|
u16 layout_count;
|
||||||
|
struct efi_hii_keyboard_layout layout[];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* HII protocols
|
* HII protocols
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -16,6 +16,7 @@ const efi_guid_t efi_guid_hii_database_protocol
|
||||||
const efi_guid_t efi_guid_hii_string_protocol = EFI_HII_STRING_PROTOCOL_GUID;
|
const efi_guid_t efi_guid_hii_string_protocol = EFI_HII_STRING_PROTOCOL_GUID;
|
||||||
|
|
||||||
static LIST_HEAD(efi_package_lists);
|
static LIST_HEAD(efi_package_lists);
|
||||||
|
static LIST_HEAD(efi_keyboard_layout_list);
|
||||||
|
|
||||||
struct efi_hii_packagelist {
|
struct efi_hii_packagelist {
|
||||||
struct list_head link;
|
struct list_head link;
|
||||||
|
@ -24,6 +25,7 @@ struct efi_hii_packagelist {
|
||||||
u32 max_string_id;
|
u32 max_string_id;
|
||||||
struct list_head string_tables; /* list of efi_string_table */
|
struct list_head string_tables; /* list of efi_string_table */
|
||||||
struct list_head guid_list;
|
struct list_head guid_list;
|
||||||
|
struct list_head keyboard_packages;
|
||||||
|
|
||||||
/* we could also track fonts, images, etc */
|
/* we could also track fonts, images, etc */
|
||||||
};
|
};
|
||||||
|
@ -86,6 +88,17 @@ struct efi_guid_data {
|
||||||
struct efi_hii_guid_package package;
|
struct efi_hii_guid_package package;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct efi_keyboard_layout_data {
|
||||||
|
struct list_head link; /* in package */
|
||||||
|
struct list_head link_sys; /* in global list */
|
||||||
|
struct efi_hii_keyboard_layout keyboard_layout;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct efi_keyboard_package_data {
|
||||||
|
struct list_head link; /* in package_list */
|
||||||
|
struct list_head keyboard_layout_list;
|
||||||
|
};
|
||||||
|
|
||||||
static void free_strings_table(struct efi_string_table *stbl)
|
static void free_strings_table(struct efi_string_table *stbl)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -253,6 +266,78 @@ add_guid_package(struct efi_hii_packagelist *hii,
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void free_keyboard_layouts(struct efi_keyboard_package_data *package)
|
||||||
|
{
|
||||||
|
struct efi_keyboard_layout_data *layout_data;
|
||||||
|
|
||||||
|
while (!list_empty(&package->keyboard_layout_list)) {
|
||||||
|
layout_data = list_first_entry(&package->keyboard_layout_list,
|
||||||
|
struct efi_keyboard_layout_data,
|
||||||
|
link);
|
||||||
|
list_del(&layout_data->link);
|
||||||
|
list_del(&layout_data->link_sys);
|
||||||
|
free(layout_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_keyboard_package(struct efi_hii_packagelist *hii)
|
||||||
|
{
|
||||||
|
struct efi_keyboard_package_data *package;
|
||||||
|
|
||||||
|
while (!list_empty(&hii->keyboard_packages)) {
|
||||||
|
package = list_first_entry(&hii->keyboard_packages,
|
||||||
|
struct efi_keyboard_package_data,
|
||||||
|
link);
|
||||||
|
free_keyboard_layouts(package);
|
||||||
|
list_del(&package->link);
|
||||||
|
free(package);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static efi_status_t
|
||||||
|
add_keyboard_package(struct efi_hii_packagelist *hii,
|
||||||
|
struct efi_hii_keyboard_package *keyboard_package)
|
||||||
|
{
|
||||||
|
struct efi_keyboard_package_data *package_data;
|
||||||
|
struct efi_hii_keyboard_layout *layout;
|
||||||
|
struct efi_keyboard_layout_data *layout_data;
|
||||||
|
u16 layout_count, layout_length;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
package_data = malloc(sizeof(*package_data));
|
||||||
|
if (!package_data)
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
INIT_LIST_HEAD(&package_data->link);
|
||||||
|
INIT_LIST_HEAD(&package_data->keyboard_layout_list);
|
||||||
|
|
||||||
|
layout = &keyboard_package->layout[0];
|
||||||
|
layout_count = get_unaligned_le16(&keyboard_package->layout_count);
|
||||||
|
for (i = 0; i < layout_count; i++) {
|
||||||
|
layout_length = get_unaligned_le16(&layout->layout_length);
|
||||||
|
layout_data = malloc(sizeof(*layout_data) + layout_length);
|
||||||
|
if (!layout_data)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
memcpy(&layout_data->keyboard_layout, layout, layout_length);
|
||||||
|
list_add_tail(&layout_data->link,
|
||||||
|
&package_data->keyboard_layout_list);
|
||||||
|
list_add_tail(&layout_data->link_sys,
|
||||||
|
&efi_keyboard_layout_list);
|
||||||
|
|
||||||
|
layout += layout_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_add_tail(&package_data->link, &hii->keyboard_packages);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
|
out:
|
||||||
|
free_keyboard_layouts(package_data);
|
||||||
|
free(package_data);
|
||||||
|
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
static struct efi_hii_packagelist *new_packagelist(void)
|
static struct efi_hii_packagelist *new_packagelist(void)
|
||||||
{
|
{
|
||||||
struct efi_hii_packagelist *hii;
|
struct efi_hii_packagelist *hii;
|
||||||
|
@ -261,6 +346,7 @@ static struct efi_hii_packagelist *new_packagelist(void)
|
||||||
hii->max_string_id = 0;
|
hii->max_string_id = 0;
|
||||||
INIT_LIST_HEAD(&hii->string_tables);
|
INIT_LIST_HEAD(&hii->string_tables);
|
||||||
INIT_LIST_HEAD(&hii->guid_list);
|
INIT_LIST_HEAD(&hii->guid_list);
|
||||||
|
INIT_LIST_HEAD(&hii->keyboard_packages);
|
||||||
|
|
||||||
return hii;
|
return hii;
|
||||||
}
|
}
|
||||||
|
@ -269,6 +355,7 @@ static void free_packagelist(struct efi_hii_packagelist *hii)
|
||||||
{
|
{
|
||||||
remove_strings_package(hii);
|
remove_strings_package(hii);
|
||||||
remove_guid_package(hii);
|
remove_guid_package(hii);
|
||||||
|
remove_keyboard_package(hii);
|
||||||
|
|
||||||
list_del(&hii->link);
|
list_del(&hii->link);
|
||||||
free(hii);
|
free(hii);
|
||||||
|
@ -324,8 +411,8 @@ add_packages(struct efi_hii_packagelist *hii,
|
||||||
ret = EFI_INVALID_PARAMETER;
|
ret = EFI_INVALID_PARAMETER;
|
||||||
break;
|
break;
|
||||||
case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
|
case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
|
||||||
printf("\tKeyboard layout package not supported\n");
|
ret = add_keyboard_package(hii,
|
||||||
ret = EFI_INVALID_PARAMETER;
|
(struct efi_hii_keyboard_package *)package);
|
||||||
break;
|
break;
|
||||||
case EFI_HII_PACKAGE_ANIMATIONS:
|
case EFI_HII_PACKAGE_ANIMATIONS:
|
||||||
printf("\tAnimation package not supported\n");
|
printf("\tAnimation package not supported\n");
|
||||||
|
@ -458,7 +545,7 @@ update_package_list(const struct efi_hii_database_protocol *this,
|
||||||
ret = EFI_INVALID_PARAMETER;
|
ret = EFI_INVALID_PARAMETER;
|
||||||
break;
|
break;
|
||||||
case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
|
case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
|
||||||
printf("\tKeyboard layout package not supported\n");
|
remove_keyboard_package(hii);
|
||||||
break;
|
break;
|
||||||
case EFI_HII_PACKAGE_ANIMATIONS:
|
case EFI_HII_PACKAGE_ANIMATIONS:
|
||||||
printf("\tAnimation package not supported\n");
|
printf("\tAnimation package not supported\n");
|
||||||
|
@ -546,7 +633,8 @@ list_package_lists(const struct efi_hii_database_protocol *this,
|
||||||
ret = EFI_INVALID_PARAMETER;
|
ret = EFI_INVALID_PARAMETER;
|
||||||
continue;
|
continue;
|
||||||
case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
|
case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
|
||||||
printf("\tKeyboard layout package not supported\n");
|
if (!list_empty(&hii->keyboard_packages))
|
||||||
|
break;
|
||||||
continue;
|
continue;
|
||||||
case EFI_HII_PACKAGE_ANIMATIONS:
|
case EFI_HII_PACKAGE_ANIMATIONS:
|
||||||
printf("\tAnimation package not supported\n");
|
printf("\tAnimation package not supported\n");
|
||||||
|
@ -620,9 +708,30 @@ find_keyboard_layouts(const struct efi_hii_database_protocol *this,
|
||||||
u16 *key_guid_buffer_length,
|
u16 *key_guid_buffer_length,
|
||||||
efi_guid_t *key_guid_buffer)
|
efi_guid_t *key_guid_buffer)
|
||||||
{
|
{
|
||||||
|
struct efi_keyboard_layout_data *layout_data;
|
||||||
|
int package_cnt, package_max;
|
||||||
|
efi_status_t ret = EFI_SUCCESS;
|
||||||
|
|
||||||
EFI_ENTRY("%p, %p, %p", this, key_guid_buffer_length, key_guid_buffer);
|
EFI_ENTRY("%p, %p, %p", this, key_guid_buffer_length, key_guid_buffer);
|
||||||
|
|
||||||
return EFI_EXIT(EFI_NOT_FOUND);
|
if (!key_guid_buffer_length ||
|
||||||
|
(*key_guid_buffer_length && !key_guid_buffer))
|
||||||
|
return EFI_EXIT(EFI_INVALID_PARAMETER);
|
||||||
|
|
||||||
|
package_cnt = 0;
|
||||||
|
package_max = *key_guid_buffer_length / sizeof(*key_guid_buffer);
|
||||||
|
list_for_each_entry(layout_data, &efi_keyboard_layout_list, link_sys) {
|
||||||
|
package_cnt++;
|
||||||
|
if (package_cnt <= package_max)
|
||||||
|
memcpy(key_guid_buffer++,
|
||||||
|
&layout_data->keyboard_layout.guid,
|
||||||
|
sizeof(*key_guid_buffer));
|
||||||
|
else
|
||||||
|
ret = EFI_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
*key_guid_buffer_length = package_cnt * sizeof(*key_guid_buffer);
|
||||||
|
|
||||||
|
return EFI_EXIT(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static efi_status_t EFIAPI
|
static efi_status_t EFIAPI
|
||||||
|
@ -631,10 +740,38 @@ get_keyboard_layout(const struct efi_hii_database_protocol *this,
|
||||||
u16 *keyboard_layout_length,
|
u16 *keyboard_layout_length,
|
||||||
struct efi_hii_keyboard_layout *keyboard_layout)
|
struct efi_hii_keyboard_layout *keyboard_layout)
|
||||||
{
|
{
|
||||||
|
struct efi_keyboard_layout_data *layout_data;
|
||||||
|
u16 layout_length;
|
||||||
|
|
||||||
EFI_ENTRY("%p, %pUl, %p, %p", this, key_guid, keyboard_layout_length,
|
EFI_ENTRY("%p, %pUl, %p, %p", this, key_guid, keyboard_layout_length,
|
||||||
keyboard_layout);
|
keyboard_layout);
|
||||||
|
|
||||||
|
if (!keyboard_layout_length ||
|
||||||
|
(*keyboard_layout_length && !keyboard_layout))
|
||||||
|
return EFI_EXIT(EFI_INVALID_PARAMETER);
|
||||||
|
|
||||||
|
/* TODO: no notion of current keyboard layout */
|
||||||
|
if (!key_guid)
|
||||||
|
return EFI_EXIT(EFI_INVALID_PARAMETER);
|
||||||
|
|
||||||
|
list_for_each_entry(layout_data, &efi_keyboard_layout_list, link_sys) {
|
||||||
|
if (!guidcmp(&layout_data->keyboard_layout.guid, key_guid))
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
return EFI_EXIT(EFI_NOT_FOUND);
|
return EFI_EXIT(EFI_NOT_FOUND);
|
||||||
|
|
||||||
|
found:
|
||||||
|
layout_length =
|
||||||
|
get_unaligned_le16(&layout_data->keyboard_layout.layout_length);
|
||||||
|
if (*keyboard_layout_length < layout_length) {
|
||||||
|
*keyboard_layout_length = layout_length;
|
||||||
|
return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(keyboard_layout, &layout_data->keyboard_layout, layout_length);
|
||||||
|
|
||||||
|
return EFI_EXIT(EFI_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static efi_status_t EFIAPI
|
static efi_status_t EFIAPI
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue