efi_selftest: add HII database protocols test
[oweals/u-boot.git] / lib / efi_selftest / efi_selftest_hii.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * efi_selftest_hii
4  *
5  * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited
6  *
7  * Test HII database protocols
8  */
9
10 #include <efi_selftest.h>
11 #include <malloc.h>
12 #include "efi_selftest_hii_data.c"
13
14 #define PRINT_TESTNAME efi_st_printf("%s:\n", __func__)
15
16 static struct efi_boot_services *boottime;
17
18 static const efi_guid_t hii_database_protocol_guid =
19         EFI_HII_DATABASE_PROTOCOL_GUID;
20 static const efi_guid_t hii_string_protocol_guid =
21         EFI_HII_STRING_PROTOCOL_GUID;
22
23 static struct efi_hii_database_protocol *hii_database_protocol;
24 static struct efi_hii_string_protocol *hii_string_protocol;
25
26 /*
27  * Setup unit test.
28  *
29  * @handle:     handle of the loaded image
30  * @systable:   system table
31  *
32  * @return:     EFI_ST_SUCCESS for success
33  */
34 static int setup(const efi_handle_t handle,
35                  const struct efi_system_table *systable)
36 {
37         efi_status_t ret;
38
39         boottime = systable->boottime;
40
41         /* HII database protocol */
42         ret = boottime->locate_protocol(&hii_database_protocol_guid, NULL,
43                                         (void **)&hii_database_protocol);
44         if (ret != EFI_SUCCESS) {
45                 hii_database_protocol = NULL;
46                 efi_st_error("HII database protocol is not available.\n");
47                 return EFI_ST_FAILURE;
48         }
49
50         /* HII string protocol */
51         ret = boottime->locate_protocol(&hii_string_protocol_guid, NULL,
52                                         (void **)&hii_string_protocol);
53         if (ret != EFI_SUCCESS) {
54                 hii_string_protocol = NULL;
55                 efi_st_error("HII string protocol is not available.\n");
56                 return EFI_ST_FAILURE;
57         }
58
59         return EFI_ST_SUCCESS;
60 }
61
62 /*
63  * HII database protocol tests
64  */
65
66 /**
67  * test_hii_database_new_package_list() - test creation and removal of
68  *      package list
69  *
70  * This test adds a new package list and then tries to remove it using
71  * the provided handle.
72  *
73  * @Return:     status code
74  */
75 static int test_hii_database_new_package_list(void)
76 {
77         efi_hii_handle_t handle;
78         efi_status_t ret;
79
80         PRINT_TESTNAME;
81         ret = hii_database_protocol->new_package_list(hii_database_protocol,
82                         (struct efi_hii_package_list_header *)packagelist1,
83                         NULL, &handle);
84         if (ret != EFI_SUCCESS || !handle) {
85                 efi_st_error("new_package_list returned %u\n",
86                              (unsigned int)ret);
87                 return EFI_ST_FAILURE;
88         }
89
90         ret = hii_database_protocol->remove_package_list(hii_database_protocol,
91                         handle);
92         if (ret != EFI_SUCCESS) {
93                 efi_st_error("remove_package_list returned %u\n",
94                              (unsigned int)ret);
95                 return EFI_ST_FAILURE;
96         }
97
98         return EFI_ST_SUCCESS;
99 }
100
101 /**
102  * test_hii_database_update_package_list() - test update of package list
103  *
104  * This test adds a new package list and then tries to update it using
105  * another package list.
106  *
107  * @Return:     status code
108  */
109 static int test_hii_database_update_package_list(void)
110 {
111         efi_hii_handle_t handle = NULL;
112         efi_status_t ret;
113         int result = EFI_ST_FAILURE;
114
115         PRINT_TESTNAME;
116         ret = hii_database_protocol->new_package_list(hii_database_protocol,
117                         (struct efi_hii_package_list_header *)packagelist1,
118                         NULL, &handle);
119         if (ret != EFI_SUCCESS || !handle) {
120                 efi_st_error("new_package_list returned %u\n",
121                              (unsigned int)ret);
122                 return EFI_ST_FAILURE;
123         }
124
125         ret = hii_database_protocol->update_package_list(hii_database_protocol,
126                         handle,
127                         (struct efi_hii_package_list_header *)packagelist2);
128         if (ret != EFI_SUCCESS || !handle) {
129                 efi_st_error("new_package_list returned %u\n",
130                              (unsigned int)ret);
131                 goto out;
132         }
133
134         result = EFI_ST_SUCCESS;
135
136 out:
137         if (handle) {
138                 ret = hii_database_protocol->remove_package_list(
139                                 hii_database_protocol, handle);
140                 if (ret != EFI_SUCCESS) {
141                         efi_st_error("remove_package_list returned %u\n",
142                                      (unsigned int)ret);
143                         return EFI_ST_FAILURE;
144                 }
145         }
146
147         return result;
148 }
149
150 /**
151  * test_hii_database_list_package_lists() - test listing of package lists
152  *
153  * This test adds two package lists and then tries to enumerate them
154  * against different package types. We will get an array of handles.
155  *
156  * @Return:     status code
157  */
158 static int test_hii_database_list_package_lists(void)
159 {
160         efi_hii_handle_t handle1 = NULL, handle2 = NULL, *handles;
161         efi_uintn_t handles_size;
162         efi_status_t ret;
163         int result = EFI_ST_FAILURE;
164
165         PRINT_TESTNAME;
166         ret = hii_database_protocol->new_package_list(hii_database_protocol,
167                         (struct efi_hii_package_list_header *)packagelist1,
168                         NULL, &handle1);
169         if (ret != EFI_SUCCESS || !handle1) {
170                 efi_st_error("new_package_list returned %u\n",
171                              (unsigned int)ret);
172                 goto out;
173         }
174
175         ret = hii_database_protocol->new_package_list(hii_database_protocol,
176                         (struct efi_hii_package_list_header *)packagelist2,
177                         NULL, &handle2);
178         if (ret != EFI_SUCCESS || !handle2) {
179                 efi_st_error("new_package_list returned %u\n",
180                              (unsigned int)ret);
181                 goto out;
182         }
183
184         /* TYPE_ALL */
185         handles = NULL;
186         handles_size = 0;
187         ret = hii_database_protocol->list_package_lists(hii_database_protocol,
188                         EFI_HII_PACKAGE_TYPE_ALL, NULL,
189                         &handles_size, handles);
190         if (ret != EFI_BUFFER_TOO_SMALL) {
191                 efi_st_error("list_package_lists returned %u\n",
192                              (unsigned int)ret);
193                 goto out;
194         }
195         handles = malloc(handles_size);
196         if (!handles) {
197                 efi_st_error("malloc failed\n");
198                 goto out;
199         }
200         ret = hii_database_protocol->list_package_lists(hii_database_protocol,
201                         EFI_HII_PACKAGE_TYPE_ALL, NULL,
202                         &handles_size, handles);
203         if (ret != EFI_SUCCESS) {
204                 efi_st_error("list_package_lists returned %u\n",
205                              (unsigned int)ret);
206                 goto out;
207         }
208         efi_st_printf("list_package_lists returned %ld handles\n",
209                       handles_size / sizeof(*handles));
210         free(handles);
211
212         /* STRINGS */
213         handles = NULL;
214         handles_size = 0;
215         ret = hii_database_protocol->list_package_lists(hii_database_protocol,
216                         EFI_HII_PACKAGE_STRINGS, NULL,
217                         &handles_size, handles);
218         if (ret != EFI_BUFFER_TOO_SMALL) {
219                 efi_st_error("list_package_lists returned %u\n",
220                              (unsigned int)ret);
221                 ret = EFI_ST_FAILURE;
222                 goto out;
223         }
224         handles = malloc(handles_size);
225         if (!handles) {
226                 efi_st_error("malloc failed\n");
227                 ret = EFI_ST_FAILURE;
228                 goto out;
229         }
230         ret = hii_database_protocol->list_package_lists(hii_database_protocol,
231                         EFI_HII_PACKAGE_STRINGS, NULL,
232                         &handles_size, handles);
233         if (ret != EFI_SUCCESS) {
234                 efi_st_error("list_package_lists returned %u\n",
235                              (unsigned int)ret);
236                 ret = EFI_ST_FAILURE;
237                 goto out;
238         }
239         efi_st_printf("list_package_lists returned %ld strings handles\n",
240                       handles_size / sizeof(*handles));
241         free(handles);
242
243         /* GUID */
244         handles = NULL;
245         handles_size = 0;
246         ret = hii_database_protocol->list_package_lists(hii_database_protocol,
247                         EFI_HII_PACKAGE_TYPE_GUID, &package_guid,
248                         &handles_size, handles);
249         if (ret != EFI_BUFFER_TOO_SMALL) {
250                 efi_st_error("list_package_lists returned %u\n",
251                              (unsigned int)ret);
252                 ret = EFI_ST_FAILURE;
253                 goto out;
254         }
255         handles = malloc(handles_size);
256         if (!handles) {
257                 efi_st_error("malloc failed\n");
258                 ret = EFI_ST_FAILURE;
259                 goto out;
260         }
261         ret = hii_database_protocol->list_package_lists(hii_database_protocol,
262                         EFI_HII_PACKAGE_TYPE_GUID, &package_guid,
263                         &handles_size, handles);
264         if (ret != EFI_SUCCESS) {
265                 efi_st_error("list_package_lists returned %u\n",
266                              (unsigned int)ret);
267                 ret = EFI_ST_FAILURE;
268                 goto out;
269         }
270         efi_st_printf("list_package_lists returned %ld guid handles\n",
271                       handles_size / sizeof(*handles));
272         free(handles);
273
274         /* KEYBOARD_LAYOUT */
275         handles = NULL;
276         handles_size = 0;
277         ret = hii_database_protocol->list_package_lists(hii_database_protocol,
278                         EFI_HII_PACKAGE_KEYBOARD_LAYOUT, NULL,
279                         &handles_size, handles);
280         if (ret != EFI_BUFFER_TOO_SMALL) {
281                 efi_st_error("list_package_lists returned %u\n",
282                              (unsigned int)ret);
283                 ret = EFI_ST_FAILURE;
284                 goto out;
285         }
286         handles = malloc(handles_size);
287         if (!handles) {
288                 efi_st_error("malloc failed\n");
289                 ret = EFI_ST_FAILURE;
290                 goto out;
291         }
292         ret = hii_database_protocol->list_package_lists(hii_database_protocol,
293                         EFI_HII_PACKAGE_KEYBOARD_LAYOUT, NULL,
294                         &handles_size, handles);
295         if (ret != EFI_SUCCESS) {
296                 efi_st_error("list_package_lists returned %u\n",
297                              (unsigned int)ret);
298                 ret = EFI_ST_FAILURE;
299                 goto out;
300         }
301         efi_st_printf("list_package_lists returned %ld keyboard layout handles\n",
302                       handles_size / sizeof(*handles));
303         free(handles);
304
305         result = EFI_ST_SUCCESS;
306
307 out:
308         if (handle1) {
309                 ret = hii_database_protocol->remove_package_list(
310                                 hii_database_protocol, handle1);
311                 if (ret != EFI_SUCCESS)
312                         efi_st_error("remove_package_list returned %u\n",
313                                      (unsigned int)ret);
314         }
315         if (handle2) {
316                 ret = hii_database_protocol->remove_package_list(
317                                 hii_database_protocol, handle2);
318                 if (ret != EFI_SUCCESS)
319                         efi_st_error("remove_package_list returned %u\n",
320                                      (unsigned int)ret);
321         }
322
323         return result;
324 }
325
326 /**
327  * test_hii_database_export_package_lists() - test export of package lists
328  *
329  * @Return:     status code
330  */
331 static int test_hii_database_export_package_lists(void)
332 {
333         PRINT_TESTNAME;
334         /* export_package_lists() not implemented yet */
335         return EFI_ST_SUCCESS;
336 }
337
338 /**
339  * test_hii_database_register_package_notify() - test registration of
340  *      notification function
341  *
342  * @Return:     status code
343  */
344 static int test_hii_database_register_package_notify(void)
345 {
346         PRINT_TESTNAME;
347         /* register_package_notify() not implemented yet */
348         return EFI_ST_SUCCESS;
349 }
350
351 /**
352  * test_hii_database_unregister_package_notify() - test removal of
353  *      notification function
354  *
355  * @Return:     status code
356  */
357 static int test_hii_database_unregister_package_notify(void)
358 {
359         PRINT_TESTNAME;
360         /* unregsiter_package_notify() not implemented yet */
361         return EFI_ST_SUCCESS;
362 }
363
364 /**
365  * test_hii_database_find_keyboard_layouts() - test listing of
366  *      all the keyboard layouts in the system
367  *
368  * This test adds two package lists, each of which has two keyboard layouts
369  * and then tries to enumerate them. We will get an array of handles.
370  *
371  * @Return:     status code
372  */
373 static int test_hii_database_find_keyboard_layouts(void)
374 {
375         efi_hii_handle_t handle1 = NULL, handle2 = NULL;
376         efi_guid_t *guids;
377         u16 guids_size;
378         efi_status_t ret;
379         int result = EFI_ST_FAILURE;
380
381         PRINT_TESTNAME;
382         ret = hii_database_protocol->new_package_list(hii_database_protocol,
383                         (struct efi_hii_package_list_header *)packagelist1,
384                         NULL, &handle1);
385         if (ret != EFI_SUCCESS || !handle1) {
386                 efi_st_error("new_package_list returned %u\n",
387                              (unsigned int)ret);
388                 goto out;
389         }
390
391         ret = hii_database_protocol->new_package_list(hii_database_protocol,
392                         (struct efi_hii_package_list_header *)packagelist2,
393                         NULL, &handle2);
394         if (ret != EFI_SUCCESS || !handle2) {
395                 efi_st_error("new_package_list returned %u\n",
396                              (unsigned int)ret);
397                 goto out;
398         }
399
400         guids = NULL;
401         guids_size = 0;
402         ret = hii_database_protocol->find_keyboard_layouts(
403                         hii_database_protocol, &guids_size, guids);
404         if (ret != EFI_BUFFER_TOO_SMALL) {
405                 efi_st_error("find_keyboard_layouts returned %u\n",
406                              (unsigned int)ret);
407                 goto out;
408         }
409         guids = malloc(guids_size);
410         if (!guids) {
411                 efi_st_error("malloc failed\n");
412                 goto out;
413         }
414         ret = hii_database_protocol->find_keyboard_layouts(
415                         hii_database_protocol, &guids_size, guids);
416         if (ret != EFI_SUCCESS) {
417                 efi_st_error("find_keyboard_layouts returned %u\n",
418                              (unsigned int)ret);
419                 goto out;
420         }
421         free(guids);
422
423         efi_st_printf("find_keyboard_layouts returned %ld guids\n",
424                       guids_size / sizeof(*guids));
425
426         result = EFI_ST_SUCCESS;
427
428 out:
429         if (handle1) {
430                 ret = hii_database_protocol->remove_package_list(
431                                 hii_database_protocol, handle1);
432                 if (ret != EFI_SUCCESS)
433                         efi_st_error("remove_package_list returned %u\n",
434                                      (unsigned int)ret);
435         }
436         if (handle2) {
437                 ret = hii_database_protocol->remove_package_list(
438                                 hii_database_protocol, handle2);
439                 if (ret != EFI_SUCCESS)
440                         efi_st_error("remove_package_list returned %u\n",
441                                      (unsigned int)ret);
442         }
443
444         return result;
445 }
446
447 /**
448  * test_hii_database_get_keyboard_layout() - test retrieval of keyboard layout
449  *
450  * This test adds two package lists, each of which has two keyboard layouts
451  * and then tries to get a handle to keyboard layout with a specific guid
452  * and the current one.
453  *
454  * @Return:     status code
455  */
456 static int test_hii_database_get_keyboard_layout(void)
457 {
458         efi_hii_handle_t handle1 = NULL, handle2 = NULL;
459         struct efi_hii_keyboard_layout *kb_layout;
460         u16 kb_layout_size;
461         efi_status_t ret;
462         int result = EFI_ST_FAILURE;
463
464         PRINT_TESTNAME;
465         ret = hii_database_protocol->new_package_list(hii_database_protocol,
466                         (struct efi_hii_package_list_header *)packagelist1,
467                         NULL, &handle1);
468         if (ret != EFI_SUCCESS || !handle1) {
469                 efi_st_error("new_package_list returned %u\n",
470                              (unsigned int)ret);
471                 goto out;
472         }
473
474         ret = hii_database_protocol->new_package_list(hii_database_protocol,
475                         (struct efi_hii_package_list_header *)packagelist2,
476                         NULL, &handle2);
477         if (ret != EFI_SUCCESS || !handle2) {
478                 efi_st_error("new_package_list returned %u\n",
479                              (unsigned int)ret);
480                 goto out;
481         }
482
483         /* specific keyboard_layout(guid11) */
484         kb_layout = NULL;
485         kb_layout_size = 0;
486         ret = hii_database_protocol->get_keyboard_layout(hii_database_protocol,
487                         &kb_layout_guid11, &kb_layout_size, kb_layout);
488         if (ret != EFI_BUFFER_TOO_SMALL) {
489                 efi_st_error("get_keyboard_layout returned %u\n",
490                              (unsigned int)ret);
491                 goto out;
492         }
493         kb_layout = malloc(kb_layout_size);
494         if (!kb_layout) {
495                 efi_st_error("malloc failed\n");
496                 goto out;
497         }
498         ret = hii_database_protocol->get_keyboard_layout(hii_database_protocol,
499                         &kb_layout_guid11, &kb_layout_size, kb_layout);
500         if (ret != EFI_SUCCESS) {
501                 efi_st_error("get_keyboard_layout returned %u\n",
502                              (unsigned int)ret);
503                 goto out;
504         }
505         free(kb_layout);
506
507         /* current */
508         kb_layout = NULL;
509         kb_layout_size = 0;
510         ret = hii_database_protocol->get_keyboard_layout(hii_database_protocol,
511                         NULL, &kb_layout_size, kb_layout);
512         if (ret != EFI_INVALID_PARAMETER) {
513                 efi_st_error("get_keyboard_layout returned %u\n",
514                              (unsigned int)ret);
515                 goto out;
516         }
517
518         result = EFI_ST_SUCCESS;
519
520 out:
521         if (handle1) {
522                 ret = hii_database_protocol->remove_package_list(
523                                 hii_database_protocol, handle1);
524                 if (ret != EFI_SUCCESS)
525                         efi_st_error("remove_package_list returned %u\n",
526                                      (unsigned int)ret);
527         }
528         if (handle2) {
529                 ret = hii_database_protocol->remove_package_list(
530                                 hii_database_protocol, handle2);
531                 if (ret != EFI_SUCCESS)
532                         efi_st_error("remove_package_list returned %u\n",
533                                      (unsigned int)ret);
534         }
535
536         return result;
537 }
538
539 /**
540  * test_hii_database_set_keyboard_layout() - test change of
541  *      current keyboard layout
542  *
543  * @Return:     status code
544  */
545 static int test_hii_database_set_keyboard_layout(void)
546 {
547         PRINT_TESTNAME;
548         /* set_keyboard_layout() not implemented yet */
549         return EFI_ST_SUCCESS;
550 }
551
552 /**
553  * test_hii_database_get_package_list_handle() - test retrieval of
554  *      driver associated with a package list
555  *
556  * This test adds a package list, and then tries to get a handle to driver
557  * which is associated with a package list.
558  *
559  * @Return:     status code
560  */
561 static int test_hii_database_get_package_list_handle(void)
562 {
563         efi_hii_handle_t handle = NULL;
564         efi_handle_t driver_handle;
565         efi_status_t ret;
566         int result = EFI_ST_FAILURE;
567
568         PRINT_TESTNAME;
569         driver_handle = (efi_handle_t)0x12345678; /* dummy */
570         ret = hii_database_protocol->new_package_list(hii_database_protocol,
571                         (struct efi_hii_package_list_header *)packagelist1,
572                         driver_handle, &handle);
573         if (ret != EFI_SUCCESS || !handle) {
574                 efi_st_error("new_package_list returned %u\n",
575                              (unsigned int)ret);
576                 return EFI_ST_FAILURE;
577         }
578
579         driver_handle = NULL;
580         ret = hii_database_protocol->get_package_list_handle(
581                         hii_database_protocol, handle, &driver_handle);
582         if (ret != EFI_SUCCESS || driver_handle != (efi_handle_t)0x12345678) {
583                 efi_st_error("get_package_list_handle returned %u, driver:%p\n",
584                              (unsigned int)ret, driver_handle);
585                 goto out;
586         }
587
588         result = EFI_ST_SUCCESS;
589
590 out:
591         if (handle) {
592                 ret = hii_database_protocol->remove_package_list(
593                                 hii_database_protocol, handle);
594                 if (ret != EFI_SUCCESS) {
595                         efi_st_error("remove_package_list returned %u\n",
596                                      (unsigned int)ret);
597                         return EFI_ST_FAILURE;
598                 }
599         }
600
601         return result;
602 }
603
604 static int test_hii_database_protocol(void)
605 {
606         int ret;
607
608         ret = test_hii_database_new_package_list();
609         if (ret != EFI_ST_SUCCESS)
610                 return EFI_ST_FAILURE;
611
612         ret = test_hii_database_update_package_list();
613         if (ret != EFI_ST_SUCCESS)
614                 return EFI_ST_FAILURE;
615
616         ret = test_hii_database_list_package_lists();
617         if (ret != EFI_ST_SUCCESS)
618                 return EFI_ST_FAILURE;
619
620         ret = test_hii_database_export_package_lists();
621         if (ret != EFI_ST_SUCCESS)
622                 return EFI_ST_FAILURE;
623
624         ret = test_hii_database_register_package_notify();
625         if (ret != EFI_ST_SUCCESS)
626                 return EFI_ST_FAILURE;
627
628         ret = test_hii_database_unregister_package_notify();
629         if (ret != EFI_ST_SUCCESS)
630                 return EFI_ST_FAILURE;
631
632         ret = test_hii_database_find_keyboard_layouts();
633         if (ret != EFI_ST_SUCCESS)
634                 return EFI_ST_FAILURE;
635
636         ret = test_hii_database_get_keyboard_layout();
637         if (ret != EFI_ST_SUCCESS)
638                 return EFI_ST_FAILURE;
639
640         ret = test_hii_database_set_keyboard_layout();
641         if (ret != EFI_ST_SUCCESS)
642                 return EFI_ST_FAILURE;
643
644         ret = test_hii_database_get_package_list_handle();
645         if (ret != EFI_ST_SUCCESS)
646                 return EFI_ST_FAILURE;
647
648         return EFI_ST_SUCCESS;
649 }
650
651 /*
652  * HII string protocol tests
653  */
654
655 /**
656  * test_hii_string_new_string() - test creation of a new string entry
657  *
658  * This test adds a package list, and then tries to add a new string
659  * entry for a specific language.
660  *
661  * @Return:     status code
662  */
663 static int test_hii_string_new_string(void)
664 {
665         efi_hii_handle_t handle = NULL;
666         efi_string_id_t id;
667         efi_status_t ret;
668         int result = EFI_ST_FAILURE;
669
670         PRINT_TESTNAME;
671         ret = hii_database_protocol->new_package_list(hii_database_protocol,
672                         (struct efi_hii_package_list_header *)packagelist1,
673                         NULL, &handle);
674         if (ret != EFI_SUCCESS || !handle) {
675                 efi_st_error("new_package_list returned %u\n",
676                              (unsigned int)ret);
677                 return EFI_ST_FAILURE;
678         }
679
680         ret = hii_string_protocol->new_string(hii_string_protocol, handle,
681                                               &id, (u8 *)"en-US",
682                                               L"Japanese", L"Japanese", NULL);
683         if (ret != EFI_SUCCESS) {
684                 efi_st_error("new_string returned %u\n",
685                              (unsigned int)ret);
686                 goto out;
687         }
688         efi_st_printf("new string id is %u\n", id);
689
690         result = EFI_ST_SUCCESS;
691
692 out:
693         if (handle) {
694                 ret = hii_database_protocol->remove_package_list(
695                                 hii_database_protocol, handle);
696                 if (ret != EFI_SUCCESS) {
697                         efi_st_error("remove_package_list returned %u\n",
698                                      (unsigned int)ret);
699                         return EFI_ST_FAILURE;
700                 }
701         }
702
703         return result;
704 }
705
706 /**
707  * test_hii_string_get_string() - test retrieval of a string entry
708  *
709  * This test adds a package list, create a new string entry and then tries
710  * to get it with its string id.
711  *
712  * @Return:     status code
713  */
714 static int test_hii_string_get_string(void)
715 {
716         efi_hii_handle_t handle = NULL;
717         efi_string_id_t id;
718         efi_string_t string;
719         efi_uintn_t string_len;
720         efi_status_t ret;
721         int result = EFI_ST_FAILURE;
722
723         PRINT_TESTNAME;
724         ret = hii_database_protocol->new_package_list(hii_database_protocol,
725                         (struct efi_hii_package_list_header *)packagelist1,
726                         NULL, &handle);
727         if (ret != EFI_SUCCESS || !handle) {
728                 efi_st_error("new_package_list returned %u\n",
729                              (unsigned int)ret);
730                 return EFI_ST_FAILURE;
731         }
732
733         ret = hii_string_protocol->new_string(hii_string_protocol, handle,
734                                               &id, (u8 *)"en-US",
735                                               L"Japanese", L"Japanese", NULL);
736         if (ret != EFI_SUCCESS) {
737                 efi_st_error("new_string returned %u\n",
738                              (unsigned int)ret);
739                 goto out;
740         }
741
742         string = NULL;
743         string_len = 0;
744         ret = hii_string_protocol->get_string(hii_string_protocol,
745                         (u8 *)"en-US", handle, id, string, &string_len, NULL);
746         if (ret != EFI_BUFFER_TOO_SMALL) {
747                 efi_st_error("get_string returned %u\n",
748                              (unsigned int)ret);
749                 goto out;
750         }
751         string_len += sizeof(u16);
752         string = malloc(string_len);
753         if (!string) {
754                 efi_st_error("malloc failed\n");
755                 goto out;
756         }
757         ret = hii_string_protocol->get_string(hii_string_protocol,
758                         (u8 *)"en-US", handle, id, string, &string_len, NULL);
759         if (ret != EFI_SUCCESS) {
760                 efi_st_error("get_string returned %u\n",
761                              (unsigned int)ret);
762                 goto out;
763         }
764
765 #if 1
766         u16 *c1, *c2;
767
768         for (c1 = string, c2 = L"Japanese"; *c1 == *c2; c1++, c2++)
769                 ;
770         if (!*c1 && !*c2)
771                 result = EFI_ST_SUCCESS;
772         else
773                 result = EFI_ST_FAILURE;
774 #else
775         /* TODO: %ls */
776         efi_st_printf("got string is %s (can be wrong)\n", string);
777 #endif
778
779         result = EFI_ST_SUCCESS;
780
781 out:
782         if (handle) {
783                 ret = hii_database_protocol->remove_package_list(
784                                 hii_database_protocol, handle);
785                 if (ret != EFI_SUCCESS) {
786                         efi_st_error("remove_package_list returned %u\n",
787                                      (unsigned int)ret);
788                         return EFI_ST_FAILURE;
789                 }
790         }
791
792         return result;
793 }
794
795 /**
796  * test_hii_string_set_string() - test change of a string entry
797  *
798  * This test adds a package list, create a new string entry and then tries
799  * to modify it.
800  *
801  * @Return:     status code
802  */
803 static int test_hii_string_set_string(void)
804 {
805         efi_hii_handle_t handle = NULL;
806         efi_string_id_t id;
807         efi_status_t ret;
808         int result = EFI_ST_FAILURE;
809
810         PRINT_TESTNAME;
811         ret = hii_database_protocol->new_package_list(hii_database_protocol,
812                         (struct efi_hii_package_list_header *)packagelist1,
813                         NULL, &handle);
814         if (ret != EFI_SUCCESS || !handle) {
815                 efi_st_error("new_package_list returned %u\n",
816                              (unsigned int)ret);
817                 return EFI_ST_FAILURE;
818         }
819
820         ret = hii_string_protocol->new_string(hii_string_protocol, handle,
821                                               &id, (u8 *)"en-US",
822                                               L"Japanese", L"Japanese", NULL);
823         if (ret != EFI_SUCCESS) {
824                 efi_st_error("new_string returned %u\n",
825                              (unsigned int)ret);
826                 goto out;
827         }
828
829         ret = hii_string_protocol->set_string(hii_string_protocol, handle,
830                                               id, (u8 *)"en-US",
831                                               L"Nihongo", NULL);
832         if (ret != EFI_SUCCESS) {
833                 efi_st_error("set_string returned %u\n",
834                              (unsigned int)ret);
835                 goto out;
836         }
837
838         result = EFI_ST_SUCCESS;
839
840 out:
841         if (handle) {
842                 ret = hii_database_protocol->remove_package_list(
843                                 hii_database_protocol, handle);
844                 if (ret != EFI_SUCCESS) {
845                         efi_st_error("remove_package_list returned %u\n",
846                                      (unsigned int)ret);
847                         return EFI_ST_FAILURE;
848                 }
849         }
850
851         return result;
852 }
853
854 /**
855  * test_hii_string_get_languages() - test listing of languages
856  *
857  * This test adds a package list, and then tries to enumerate languages
858  * in it. We will get an string of language names.
859  *
860  * @Return:     status code
861  */
862 static int test_hii_string_get_languages(void)
863 {
864         efi_hii_handle_t handle = NULL;
865         u8 *languages;
866         efi_uintn_t languages_len;
867         efi_status_t ret;
868         int result = EFI_ST_FAILURE;
869
870         PRINT_TESTNAME;
871         ret = hii_database_protocol->new_package_list(hii_database_protocol,
872                         (struct efi_hii_package_list_header *)packagelist1,
873                         NULL, &handle);
874         if (ret != EFI_SUCCESS || !handle) {
875                 efi_st_error("new_package_list returned %u\n",
876                              (unsigned int)ret);
877                 return EFI_ST_FAILURE;
878         }
879
880         languages = NULL;
881         languages_len = 0;
882         ret = hii_string_protocol->get_languages(hii_string_protocol, handle,
883                         languages, &languages_len);
884         if (ret != EFI_BUFFER_TOO_SMALL) {
885                 efi_st_error("get_languages returned %u\n",
886                              (unsigned int)ret);
887                 goto out;
888         }
889         languages = malloc(languages_len);
890         if (!languages) {
891                 efi_st_error("malloc failed\n");
892                 goto out;
893         }
894         ret = hii_string_protocol->get_languages(hii_string_protocol, handle,
895                         languages, &languages_len);
896         if (ret != EFI_SUCCESS) {
897                 efi_st_error("get_languages returned %u\n",
898                              (unsigned int)ret);
899                 goto out;
900         }
901
902         efi_st_printf("got languages are %s\n", languages);
903
904         result = EFI_ST_SUCCESS;
905
906 out:
907         if (handle) {
908                 ret = hii_database_protocol->remove_package_list(
909                                 hii_database_protocol, handle);
910                 if (ret != EFI_SUCCESS) {
911                         efi_st_error("remove_package_list returned %u\n",
912                                      (unsigned int)ret);
913                         return EFI_ST_FAILURE;
914                 }
915         }
916
917         return result;
918 }
919
920 /**
921  * test_hii_string_get_secondary_languages() - test listing of secondary
922  *      languages
923  *
924  * This test adds a package list, and then tries to enumerate secondary
925  * languages with a specific language. We will get an string of language names.
926  *
927  * @Return:     status code
928  */
929 static int test_hii_string_get_secondary_languages(void)
930 {
931         efi_hii_handle_t handle = NULL;
932         u8 *languages;
933         efi_uintn_t languages_len;
934         efi_status_t ret;
935         int result = EFI_ST_FAILURE;
936
937         PRINT_TESTNAME;
938         ret = hii_database_protocol->new_package_list(hii_database_protocol,
939                         (struct efi_hii_package_list_header *)packagelist1,
940                         NULL, &handle);
941         if (ret != EFI_SUCCESS || !handle) {
942                 efi_st_error("new_package_list returned %u\n",
943                              (unsigned int)ret);
944                 return EFI_ST_FAILURE;
945         }
946
947         languages = NULL;
948         languages_len = 0;
949         ret = hii_string_protocol->get_secondary_languages(hii_string_protocol,
950                         handle, (u8 *)"en-US", languages, &languages_len);
951         if (ret == EFI_NOT_FOUND) {
952                 efi_st_printf("no secondary languages\n");
953                 result = EFI_ST_SUCCESS;
954                 goto out;
955         }
956         if (ret != EFI_BUFFER_TOO_SMALL) {
957                 efi_st_error("get_secondary_languages returned %u\n",
958                              (unsigned int)ret);
959                 goto out;
960         }
961         languages = malloc(languages_len);
962         if (!languages) {
963                 efi_st_error("malloc failed\n");
964                 goto out;
965         }
966         ret = hii_string_protocol->get_secondary_languages(hii_string_protocol,
967                         handle, (u8 *)"en-US", languages, &languages_len);
968         if (ret != EFI_SUCCESS) {
969                 efi_st_error("get_secondary_languages returned %u\n",
970                              (unsigned int)ret);
971                 goto out;
972         }
973
974         efi_st_printf("got secondary languages are %s\n", languages);
975
976         result = EFI_ST_SUCCESS;
977
978 out:
979         if (handle) {
980                 ret = hii_database_protocol->remove_package_list(
981                                 hii_database_protocol, handle);
982                 if (ret != EFI_SUCCESS) {
983                         efi_st_error("remove_package_list returned %u\n",
984                                      (unsigned int)ret);
985                         return EFI_ST_FAILURE;
986                 }
987         }
988
989         return result;
990 }
991
992 static int test_hii_string_protocol(void)
993 {
994         int ret;
995
996         ret = test_hii_string_new_string();
997         if (ret != EFI_ST_SUCCESS)
998                 return EFI_ST_FAILURE;
999
1000         ret = test_hii_string_get_string();
1001         if (ret != EFI_ST_SUCCESS)
1002                 return EFI_ST_FAILURE;
1003
1004         ret = test_hii_string_set_string();
1005         if (ret != EFI_ST_SUCCESS)
1006                 return EFI_ST_FAILURE;
1007
1008         ret = test_hii_string_get_languages();
1009         if (ret != EFI_ST_SUCCESS)
1010                 return EFI_ST_FAILURE;
1011
1012         ret = test_hii_string_get_secondary_languages();
1013         if (ret != EFI_ST_SUCCESS)
1014                 return EFI_ST_FAILURE;
1015
1016         return EFI_ST_SUCCESS;
1017 }
1018
1019 /*
1020  * Execute unit test.
1021  *
1022  * @return:     EFI_ST_SUCCESS for success, EFI_ST_FAILURE for failure
1023  */
1024 static int execute(void)
1025 {
1026         int ret;
1027
1028         /* HII database protocol */
1029         ret = test_hii_database_protocol();
1030         if (ret != EFI_ST_SUCCESS)
1031                 return EFI_ST_FAILURE;
1032
1033         /* HII string protocol */
1034         ret = test_hii_string_protocol();
1035         if (ret != EFI_ST_SUCCESS)
1036                 return EFI_ST_FAILURE;
1037
1038         return EFI_ST_SUCCESS;
1039 }
1040
1041 EFI_UNIT_TEST(hii) = {
1042         .name = "HII database protocols",
1043         .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
1044         .setup = setup,
1045         .execute = execute,
1046 };