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