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.aka...@linaro.org>
---
 include/efi_api.h        |  11 +++
 lib/efi_loader/efi_hii.c | 141 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 147 insertions(+), 5 deletions(-)

diff --git a/include/efi_api.h b/include/efi_api.h
index 7209f268c78f..954d2414c5c7 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -844,6 +844,17 @@ struct efi_hii_guid_package {
        char data[];
 } __packed;
 
+/*
+ * Keyboard layout package
+ */
+
+struct efi_hii_keyboard_layout_package {
+       struct efi_hii_package_header header;
+       u8 layout_count;
+       u8 __pad;
+       struct efi_hii_keyboard_layout layout[];
+} __packed;
+
 typedef void *efi_hii_handle_t;
 
 struct efi_hii_database_protocol {
diff --git a/lib/efi_loader/efi_hii.c b/lib/efi_loader/efi_hii.c
index 036aa8eac956..fefe3a861387 100644
--- a/lib/efi_loader/efi_hii.c
+++ b/lib/efi_loader/efi_hii.c
@@ -17,6 +17,7 @@ const efi_guid_t efi_guid_hii_string_protocol = 
EFI_HII_STRING_PROTOCOL_GUID;
 const u32 hii_package_signature = 0x68696770; /* "higp" */
 
 static LIST_HEAD(efi_package_lists);
+static LIST_HEAD(efi_kb_layout_list);
 
 struct efi_hii_packagelist {
        struct list_head link;
@@ -26,6 +27,7 @@ struct efi_hii_packagelist {
        u32 max_string_id;
        struct list_head string_tables;     /* list of efi_string_table */
        struct list_head guid_list;
+       struct list_head kb_layout_packages;
 
        /* we could also track fonts, images, etc */
 };
@@ -53,6 +55,17 @@ struct efi_guid_data {
        struct efi_hii_guid_package package;
 };
 
+struct efi_kb_layout_data {
+       struct list_head link;          /* in package */
+       struct list_head link_sys;      /* in global list */
+       struct efi_hii_keyboard_layout kb_layout;
+};
+
+struct efi_kb_layout_package_data {
+       struct list_head link;          /* in package_list */
+       struct list_head kb_layout_list;
+};
+
 static void free_strings_table(struct efi_string_table *stbl)
 {
        int i;
@@ -213,6 +226,74 @@ add_guid_package(struct efi_hii_packagelist *hii,
        return EFI_SUCCESS;
 }
 
+static void free_keyboard_layouts(struct efi_kb_layout_package_data *package)
+{
+       struct efi_kb_layout_data *data;
+
+       while (!list_empty(&package->kb_layout_list)) {
+               data = list_first_entry(&package->kb_layout_list,
+                                       struct efi_kb_layout_data,
+                                       link);
+               list_del(&data->link);
+               list_del(&data->link_sys);
+               free(data);
+       }
+}
+
+static void remove_keyboard_layout_package(struct efi_hii_packagelist *hii)
+{
+       struct efi_kb_layout_package_data *package;
+
+       while (!list_empty(&hii->kb_layout_packages)) {
+               package = list_first_entry(&hii->kb_layout_packages,
+                                          struct efi_kb_layout_package_data,
+                                          link);
+               free_keyboard_layouts(package);
+               list_del(&package->link);
+               free(package);
+       }
+}
+
+static efi_status_t
+add_keyboard_layout_package(struct efi_hii_packagelist *hii,
+                           struct efi_hii_keyboard_layout_package
+                               *kb_layout_package)
+{
+       struct efi_kb_layout_package_data *package;
+       struct efi_hii_keyboard_layout *layout;
+       struct efi_kb_layout_data *data;
+       int i;
+
+       package = malloc(sizeof(*package));
+       if (!package)
+               return EFI_OUT_OF_RESOURCES;
+       INIT_LIST_HEAD(&package->link);
+       INIT_LIST_HEAD(&package->kb_layout_list);
+
+       layout = &kb_layout_package->layout[0];
+       for (i = 0; i < kb_layout_package->layout_count; i++) {
+               data = malloc(sizeof(*data) + layout->layout_length);
+               if (!data)
+                       goto out;
+
+               memcpy(&data->kb_layout, layout, layout->layout_length);
+               list_add_tail(&data->link, &package->kb_layout_list);
+               list_add_tail(&data->link_sys, &efi_kb_layout_list);
+
+               layout += layout->layout_length;
+       }
+
+       list_add_tail(&package->link, &hii->kb_layout_packages);
+
+       return EFI_SUCCESS;
+
+out:
+       free_keyboard_layouts(package);
+       free(package);
+
+       return EFI_OUT_OF_RESOURCES;
+}
+
 static struct efi_hii_packagelist *new_packagelist(void)
 {
        struct efi_hii_packagelist *hii;
@@ -222,6 +303,7 @@ static struct efi_hii_packagelist *new_packagelist(void)
        hii->max_string_id = 0;
        INIT_LIST_HEAD(&hii->string_tables);
        INIT_LIST_HEAD(&hii->guid_list);
+       INIT_LIST_HEAD(&hii->kb_layout_packages);
 
        return hii;
 }
@@ -230,6 +312,7 @@ static void free_packagelist(struct efi_hii_packagelist 
*hii)
 {
        remove_strings_package(hii);
        remove_guid_package(hii);
+       remove_keyboard_layout_package(hii);
 
        list_del(&hii->link);
        free(hii);
@@ -284,8 +367,9 @@ add_packages(struct efi_hii_packagelist *hii,
                        ret = EFI_INVALID_PARAMETER;
                        break;
                case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
-                       printf("\tKeyboard layout package not supported\n");
-                       ret = EFI_INVALID_PARAMETER;
+                       ret = add_keyboard_layout_package(hii,
+                               (struct efi_hii_keyboard_layout_package *)
+                                 package);
                        break;
                case EFI_HII_PACKAGE_ANIMATIONS:
                        printf("\tAnimation package not supported\n");
@@ -418,7 +502,7 @@ update_package_list(const struct efi_hii_database_protocol 
*this,
                        ret = EFI_INVALID_PARAMETER;
                        break;
                case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
-                       printf("\tKeyboard layout package not supported\n");
+                       remove_keyboard_layout_package(hii);
                        break;
                case EFI_HII_PACKAGE_ANIMATIONS:
                        printf("\tAnimation package not supported\n");
@@ -506,7 +590,8 @@ list_package_lists(const struct efi_hii_database_protocol 
*this,
                        ret = EFI_INVALID_PARAMETER;
                        continue;
                case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
-                       printf("\tKeyboard layout package not supported\n");
+                       if (!list_empty(&hii->kb_layout_packages))
+                               break;
                        continue;
                case EFI_HII_PACKAGE_ANIMATIONS:
                        printf("\tAnimation package not supported\n");
@@ -580,9 +665,29 @@ find_keyboard_layouts(const struct 
efi_hii_database_protocol *this,
                      u16 *key_guid_buffer_length,
                      efi_guid_t *key_guid_buffer)
 {
+       struct efi_kb_layout_data *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);
 
-       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(data, &efi_kb_layout_list, link_sys) {
+               package_cnt++;
+               if (package_cnt <= package_max)
+                       memcpy(key_guid_buffer++, &data->kb_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
@@ -591,10 +696,36 @@ get_keyboard_layout(const struct 
efi_hii_database_protocol *this,
                    u16 *keyboard_layout_length,
                    struct efi_hii_keyboard_layout *keyboard_layout)
 {
+       struct efi_kb_layout_data *data;
+
        EFI_ENTRY("%p, %pUl, %p, %p", this, key_guid, keyboard_layout_length,
                  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(data, &efi_kb_layout_list, link_sys) {
+               if (!guidcmp(&data->kb_layout.guid, key_guid))
+                       goto found;
+       }
+
        return EFI_EXIT(EFI_NOT_FOUND);
+
+found:
+       if (*keyboard_layout_length < data->kb_layout.layout_length) {
+               *keyboard_layout_length = data->kb_layout.layout_length;
+               return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+       }
+
+       memcpy(keyboard_layout, &data->kb_layout,
+              sizeof(data->kb_layout.layout_length));
+
+       return EFI_EXIT(EFI_SUCCESS);
 }
 
 static efi_status_t EFIAPI
-- 
2.19.1

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to