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  */
setup(const efi_handle_t handle,const struct efi_system_table * systable)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  */
test_hii_database_new_package_list(void)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  */
test_hii_database_update_package_list(void)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  */
test_hii_database_list_package_lists(void)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 		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 
309 out:
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  */
test_hii_database_export_package_lists(void)333 static 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  */
test_hii_database_register_package_notify(void)346 static 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  */
test_hii_database_unregister_package_notify(void)359 static 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  */
test_hii_database_find_keyboard_layouts(void)375 static 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 
432 out:
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  */
test_hii_database_get_keyboard_layout(void)460 static 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 
529 out:
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  */
test_hii_database_set_keyboard_layout(void)554 static 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  */
test_hii_database_get_package_list_handle(void)582 static 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 
611 out:
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 	return result;
621 }
622 
test_hii_database_protocol(void)623 static int test_hii_database_protocol(void)
624 {
625 	int ret;
626 
627 	ret = test_hii_database_new_package_list();
628 	if (ret != EFI_ST_SUCCESS)
629 		return EFI_ST_FAILURE;
630 
631 	ret = test_hii_database_update_package_list();
632 	if (ret != EFI_ST_SUCCESS)
633 		return EFI_ST_FAILURE;
634 
635 	ret = test_hii_database_list_package_lists();
636 	if (ret != EFI_ST_SUCCESS)
637 		return EFI_ST_FAILURE;
638 
639 	ret = test_hii_database_export_package_lists();
640 	if (ret != EFI_ST_SUCCESS)
641 		return EFI_ST_FAILURE;
642 
643 	ret = test_hii_database_register_package_notify();
644 	if (ret != EFI_ST_SUCCESS)
645 		return EFI_ST_FAILURE;
646 
647 	ret = test_hii_database_unregister_package_notify();
648 	if (ret != EFI_ST_SUCCESS)
649 		return EFI_ST_FAILURE;
650 
651 	ret = test_hii_database_find_keyboard_layouts();
652 	if (ret != EFI_ST_SUCCESS)
653 		return EFI_ST_FAILURE;
654 
655 	ret = test_hii_database_get_keyboard_layout();
656 	if (ret != EFI_ST_SUCCESS)
657 		return EFI_ST_FAILURE;
658 
659 	ret = test_hii_database_set_keyboard_layout();
660 	if (ret != EFI_ST_SUCCESS)
661 		return EFI_ST_FAILURE;
662 
663 	ret = test_hii_database_get_package_list_handle();
664 	if (ret != EFI_ST_SUCCESS)
665 		return EFI_ST_FAILURE;
666 
667 	return EFI_ST_SUCCESS;
668 }
669 
670 /*
671  * HII string protocol tests
672  */
673 
674 /**
675  * test_hii_string_new_string() - test creation of a new string entry
676  *
677  * This test adds a package list, and then tries to add a new string
678  * entry for a specific language.
679  *
680  * @Return:     status code
681  */
test_hii_string_new_string(void)682 static int test_hii_string_new_string(void)
683 {
684 	efi_hii_handle_t handle = NULL;
685 	efi_string_id_t id;
686 	efi_status_t ret;
687 	int result = EFI_ST_FAILURE;
688 
689 	PRINT_TESTNAME;
690 	ret = hii_database_protocol->new_package_list(hii_database_protocol,
691 			(struct efi_hii_package_list_header *)packagelist1,
692 			NULL, &handle);
693 	if (ret != EFI_SUCCESS || !handle) {
694 		efi_st_error("new_package_list returned %u\n",
695 			     (unsigned int)ret);
696 		return EFI_ST_FAILURE;
697 	}
698 
699 	ret = hii_string_protocol->new_string(hii_string_protocol, handle,
700 					      &id, (u8 *)"en-US",
701 					      u"Japanese", u"Japanese", NULL);
702 	if (ret != EFI_SUCCESS) {
703 		efi_st_error("new_string returned %u\n",
704 			     (unsigned int)ret);
705 		goto out;
706 	}
707 	efi_st_printf("new string id is %u\n", id);
708 
709 	result = EFI_ST_SUCCESS;
710 
711 out:
712 	ret = hii_database_protocol->remove_package_list(
713 			hii_database_protocol, handle);
714 	if (ret != EFI_SUCCESS) {
715 		efi_st_error("remove_package_list returned %u\n",
716 			     (unsigned int)ret);
717 		return EFI_ST_FAILURE;
718 	}
719 
720 	return result;
721 }
722 
723 /**
724  * test_hii_string_get_string() - test retrieval of a string entry
725  *
726  * This test adds a package list, create a new string entry and then tries
727  * to get it with its string id.
728  *
729  * @Return:     status code
730  */
test_hii_string_get_string(void)731 static int test_hii_string_get_string(void)
732 {
733 	efi_hii_handle_t handle = NULL;
734 	efi_string_id_t id;
735 	efi_string_t string;
736 	efi_uintn_t string_len;
737 	efi_status_t ret;
738 	int result = EFI_ST_FAILURE;
739 
740 	PRINT_TESTNAME;
741 	ret = hii_database_protocol->new_package_list(hii_database_protocol,
742 			(struct efi_hii_package_list_header *)packagelist1,
743 			NULL, &handle);
744 	if (ret != EFI_SUCCESS || !handle) {
745 		efi_st_error("new_package_list returned %u\n",
746 			     (unsigned int)ret);
747 		return EFI_ST_FAILURE;
748 	}
749 
750 	ret = hii_string_protocol->new_string(hii_string_protocol, handle,
751 					      &id, (u8 *)"en-US",
752 					      u"Japanese", u"Japanese", NULL);
753 	if (ret != EFI_SUCCESS) {
754 		efi_st_error("new_string returned %u\n",
755 			     (unsigned int)ret);
756 		goto out;
757 	}
758 
759 	string = NULL;
760 	string_len = 0;
761 	ret = hii_string_protocol->get_string(hii_string_protocol,
762 			(u8 *)"en-US", handle, id, string, &string_len, NULL);
763 	if (ret != EFI_BUFFER_TOO_SMALL) {
764 		efi_st_error("get_string returned %u\n",
765 			     (unsigned int)ret);
766 		goto out;
767 	}
768 	string_len += sizeof(u16);
769 	ret = boottime->allocate_pool(EFI_LOADER_DATA, string_len,
770 				      (void **)&string);
771 	if (ret != EFI_SUCCESS) {
772 		efi_st_error("AllocatePool failed\n");
773 		goto out;
774 	}
775 	ret = hii_string_protocol->get_string(hii_string_protocol,
776 			(u8 *)"en-US", handle, id, string, &string_len, NULL);
777 	if (ret != EFI_SUCCESS) {
778 		efi_st_error("get_string returned %u\n",
779 			     (unsigned int)ret);
780 		goto out;
781 	}
782 
783 	if (efi_st_strcmp_16_8(string, "Japanese")) {
784 		efi_st_error("get_string returned incorrect string\n");
785 		goto out;
786 	}
787 
788 	result = EFI_ST_SUCCESS;
789 
790 out:
791 	ret = hii_database_protocol->remove_package_list(
792 			hii_database_protocol, handle);
793 	if (ret != EFI_SUCCESS) {
794 		efi_st_error("remove_package_list returned %u\n",
795 			     (unsigned int)ret);
796 		return EFI_ST_FAILURE;
797 	}
798 
799 	return result;
800 }
801 
802 /**
803  * test_hii_string_set_string() - test change of a string entry
804  *
805  * This test adds a package list, create a new string entry and then tries
806  * to modify it.
807  *
808  * @Return:     status code
809  */
test_hii_string_set_string(void)810 static int test_hii_string_set_string(void)
811 {
812 	efi_hii_handle_t handle = NULL;
813 	efi_string_id_t id;
814 	efi_status_t ret;
815 	int result = EFI_ST_FAILURE;
816 
817 	PRINT_TESTNAME;
818 	ret = hii_database_protocol->new_package_list(hii_database_protocol,
819 			(struct efi_hii_package_list_header *)packagelist1,
820 			NULL, &handle);
821 	if (ret != EFI_SUCCESS || !handle) {
822 		efi_st_error("new_package_list returned %u\n",
823 			     (unsigned int)ret);
824 		return EFI_ST_FAILURE;
825 	}
826 
827 	ret = hii_string_protocol->new_string(hii_string_protocol, handle,
828 					      &id, (u8 *)"en-US",
829 					      u"Japanese", u"Japanese", NULL);
830 	if (ret != EFI_SUCCESS) {
831 		efi_st_error("new_string returned %u\n",
832 			     (unsigned int)ret);
833 		goto out;
834 	}
835 
836 	ret = hii_string_protocol->set_string(hii_string_protocol, handle,
837 					      id, (u8 *)"en-US",
838 					      u"Nihongo", NULL);
839 	if (ret != EFI_SUCCESS) {
840 		efi_st_error("set_string returned %u\n",
841 			     (unsigned int)ret);
842 		goto out;
843 	}
844 
845 	result = EFI_ST_SUCCESS;
846 
847 out:
848 	ret = hii_database_protocol->remove_package_list(
849 			hii_database_protocol, handle);
850 	if (ret != EFI_SUCCESS) {
851 		efi_st_error("remove_package_list returned %u\n",
852 			     (unsigned int)ret);
853 		return EFI_ST_FAILURE;
854 	}
855 
856 	return result;
857 }
858 
859 /**
860  * test_hii_string_get_languages() - test listing of languages
861  *
862  * This test adds a package list, and then tries to enumerate languages
863  * in it. We will get an string of language names.
864  *
865  * @Return:     status code
866  */
test_hii_string_get_languages(void)867 static int test_hii_string_get_languages(void)
868 {
869 	efi_hii_handle_t handle = NULL;
870 	u8 *languages;
871 	efi_uintn_t languages_len;
872 	efi_status_t ret;
873 	int result = EFI_ST_FAILURE;
874 
875 	PRINT_TESTNAME;
876 	ret = hii_database_protocol->new_package_list(hii_database_protocol,
877 			(struct efi_hii_package_list_header *)packagelist1,
878 			NULL, &handle);
879 	if (ret != EFI_SUCCESS || !handle) {
880 		efi_st_error("new_package_list returned %u\n",
881 			     (unsigned int)ret);
882 		return EFI_ST_FAILURE;
883 	}
884 
885 	languages = NULL;
886 	languages_len = 0;
887 	ret = hii_string_protocol->get_languages(hii_string_protocol, handle,
888 			languages, &languages_len);
889 	if (ret != EFI_BUFFER_TOO_SMALL) {
890 		efi_st_error("get_languages returned %u\n",
891 			     (unsigned int)ret);
892 		goto out;
893 	}
894 	ret = boottime->allocate_pool(EFI_LOADER_DATA, languages_len,
895 				      (void **)&languages);
896 	if (ret != EFI_SUCCESS) {
897 		efi_st_error("AllocatePool failed\n");
898 		goto out;
899 	}
900 	ret = hii_string_protocol->get_languages(hii_string_protocol, handle,
901 			languages, &languages_len);
902 	if (ret != EFI_SUCCESS) {
903 		efi_st_error("get_languages returned %u\n",
904 			     (unsigned int)ret);
905 		goto out;
906 	}
907 
908 	efi_st_printf("Available languages: %s\n", languages);
909 
910 	result = EFI_ST_SUCCESS;
911 
912 out:
913 	ret = hii_database_protocol->remove_package_list(
914 			hii_database_protocol, handle);
915 	if (ret != EFI_SUCCESS) {
916 		efi_st_error("remove_package_list returned %u\n",
917 			     (unsigned int)ret);
918 		return EFI_ST_FAILURE;
919 	}
920 
921 	return result;
922 }
923 
924 /**
925  * test_hii_string_get_secondary_languages() - test listing of secondary
926  *	languages
927  *
928  * This test adds a package list, and then tries to enumerate secondary
929  * languages with a specific language. We will get an string of language names.
930  *
931  * @Return:     status code
932  */
test_hii_string_get_secondary_languages(void)933 static int test_hii_string_get_secondary_languages(void)
934 {
935 	efi_hii_handle_t handle = NULL;
936 	u8 *languages;
937 	efi_uintn_t languages_len;
938 	efi_status_t ret;
939 	int result = EFI_ST_FAILURE;
940 
941 	PRINT_TESTNAME;
942 	ret = hii_database_protocol->new_package_list(hii_database_protocol,
943 			(struct efi_hii_package_list_header *)packagelist1,
944 			NULL, &handle);
945 	if (ret != EFI_SUCCESS || !handle) {
946 		efi_st_error("new_package_list returned %u\n",
947 			     (unsigned int)ret);
948 		return EFI_ST_FAILURE;
949 	}
950 
951 	languages = NULL;
952 	languages_len = 0;
953 	ret = hii_string_protocol->get_secondary_languages(hii_string_protocol,
954 			handle, (u8 *)"en-US", languages, &languages_len);
955 	if (ret == EFI_NOT_FOUND) {
956 		efi_st_printf("no secondary languages\n");
957 		result = EFI_ST_SUCCESS;
958 		goto out;
959 	}
960 	if (ret != EFI_BUFFER_TOO_SMALL) {
961 		efi_st_error("get_secondary_languages returned %u\n",
962 			     (unsigned int)ret);
963 		goto out;
964 	}
965 	ret = boottime->allocate_pool(EFI_LOADER_DATA, languages_len,
966 				      (void **)&languages);
967 	if (ret != EFI_SUCCESS) {
968 		efi_st_error("AllocatePool failed\n");
969 		goto out;
970 	}
971 	ret = hii_string_protocol->get_secondary_languages(hii_string_protocol,
972 			handle, (u8 *)"en-US", languages, &languages_len);
973 	if (ret != EFI_SUCCESS) {
974 		efi_st_error("get_secondary_languages returned %u\n",
975 			     (unsigned int)ret);
976 		goto out;
977 	}
978 
979 	efi_st_printf("got secondary languages are %s\n", languages);
980 
981 	result = EFI_ST_SUCCESS;
982 
983 out:
984 	ret = hii_database_protocol->remove_package_list(
985 			hii_database_protocol, handle);
986 	if (ret != EFI_SUCCESS) {
987 		efi_st_error("remove_package_list returned %u\n",
988 			     (unsigned int)ret);
989 		return EFI_ST_FAILURE;
990 	}
991 
992 	return result;
993 }
994 
test_hii_string_protocol(void)995 static int test_hii_string_protocol(void)
996 {
997 	int ret;
998 
999 	ret = test_hii_string_new_string();
1000 	if (ret != EFI_ST_SUCCESS)
1001 		return EFI_ST_FAILURE;
1002 
1003 	ret = test_hii_string_get_string();
1004 	if (ret != EFI_ST_SUCCESS)
1005 		return EFI_ST_FAILURE;
1006 
1007 	ret = test_hii_string_set_string();
1008 	if (ret != EFI_ST_SUCCESS)
1009 		return EFI_ST_FAILURE;
1010 
1011 	ret = test_hii_string_get_languages();
1012 	if (ret != EFI_ST_SUCCESS)
1013 		return EFI_ST_FAILURE;
1014 
1015 	ret = test_hii_string_get_secondary_languages();
1016 	if (ret != EFI_ST_SUCCESS)
1017 		return EFI_ST_FAILURE;
1018 
1019 	return EFI_ST_SUCCESS;
1020 }
1021 
1022 /*
1023  * Execute unit test.
1024  *
1025  * Return:	EFI_ST_SUCCESS for success, EFI_ST_FAILURE for failure
1026  */
execute(void)1027 static int execute(void)
1028 {
1029 	int ret;
1030 
1031 	/* HII database protocol */
1032 	ret = test_hii_database_protocol();
1033 	if (ret != EFI_ST_SUCCESS)
1034 		return EFI_ST_FAILURE;
1035 
1036 	/* HII string protocol */
1037 	ret = test_hii_string_protocol();
1038 	if (ret != EFI_ST_SUCCESS)
1039 		return EFI_ST_FAILURE;
1040 
1041 	return EFI_ST_SUCCESS;
1042 }
1043 
1044 EFI_UNIT_TEST(hii) = {
1045 	.name = "HII database protocols",
1046 	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
1047 	.setup = setup,
1048 	.execute = execute,
1049 };
1050