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