]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
06c3d5b9 HS |
2 | /* |
3 | * efi_selftest_pos | |
4 | * | |
5 | * Copyright (c) 2018 Heinrich Schuchardt <[email protected]> | |
6 | * | |
06c3d5b9 HS |
7 | * Test the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. |
8 | * | |
9 | * The following services are tested: | |
10 | * OutputString, TestString, SetAttribute. | |
11 | */ | |
12 | ||
13 | #include <efi_selftest.h> | |
9967adb7 | 14 | #include <linux/libfdt.h> |
06c3d5b9 | 15 | |
68066d5b HS |
16 | static const struct efi_system_table *systemtab; |
17 | static const struct efi_boot_services *boottime; | |
06c3d5b9 HS |
18 | static const char *fdt; |
19 | ||
d8b2216c | 20 | /* This should be sufficient for */ |
06c3d5b9 HS |
21 | #define BUFFERSIZE 0x100000 |
22 | ||
68066d5b HS |
23 | static const efi_guid_t fdt_guid = EFI_FDT_GUID; |
24 | static const efi_guid_t acpi_guid = EFI_ACPI_TABLE_GUID; | |
06c3d5b9 HS |
25 | |
26 | /* | |
27 | * Convert FDT value to host endianness. | |
28 | * | |
29 | * @val FDT value | |
30 | * @return converted value | |
31 | */ | |
32 | static uint32_t f2h(fdt32_t val) | |
33 | { | |
34 | char *buf = (char *)&val; | |
35 | char i; | |
36 | ||
37 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | |
38 | /* Swap the bytes */ | |
39 | i = buf[0]; buf[0] = buf[3]; buf[3] = i; | |
40 | i = buf[1]; buf[1] = buf[2]; buf[2] = i; | |
41 | #endif | |
42 | return *(uint32_t *)buf; | |
43 | } | |
44 | ||
45 | /* | |
46 | * Return the value of a property of the FDT root node. | |
47 | * | |
48 | * @name name of the property | |
49 | * @return value of the property | |
50 | */ | |
51 | static char *get_property(const u16 *property) | |
52 | { | |
53 | struct fdt_header *header = (struct fdt_header *)fdt; | |
54 | const fdt32_t *pos; | |
55 | const char *strings; | |
56 | ||
57 | if (!header) | |
58 | return NULL; | |
59 | ||
60 | if (f2h(header->magic) != FDT_MAGIC) { | |
61 | printf("Wrong magic\n"); | |
62 | return NULL; | |
63 | } | |
64 | ||
65 | pos = (fdt32_t *)(fdt + f2h(header->off_dt_struct)); | |
66 | strings = fdt + f2h(header->off_dt_strings); | |
67 | ||
68 | for (;;) { | |
69 | switch (f2h(pos[0])) { | |
70 | case FDT_BEGIN_NODE: { | |
71 | char *c = (char *)&pos[1]; | |
72 | size_t i; | |
73 | ||
74 | for (i = 0; c[i]; ++i) | |
75 | ; | |
76 | pos = &pos[2 + (i >> 2)]; | |
77 | break; | |
78 | } | |
79 | case FDT_PROP: { | |
80 | struct fdt_property *prop = (struct fdt_property *)pos; | |
81 | const char *label = &strings[f2h(prop->nameoff)]; | |
82 | efi_status_t ret; | |
83 | ||
84 | /* Check if this is the property to be returned */ | |
85 | if (!efi_st_strcmp_16_8(property, label)) { | |
86 | char *str; | |
87 | efi_uintn_t len = f2h(prop->len); | |
88 | ||
89 | if (!len) | |
90 | return NULL; | |
91 | /* | |
92 | * The string might not be 0 terminated. | |
93 | * It is safer to make a copy. | |
94 | */ | |
95 | ret = boottime->allocate_pool( | |
96 | EFI_LOADER_DATA, len + 1, | |
97 | (void **)&str); | |
98 | if (ret != EFI_SUCCESS) { | |
99 | efi_st_printf("AllocatePool failed\n"); | |
100 | return NULL; | |
101 | } | |
102 | boottime->copy_mem(str, &pos[3], len); | |
103 | str[len] = 0; | |
104 | ||
105 | return str; | |
106 | } | |
107 | ||
108 | pos = &pos[3 + ((f2h(prop->len) + 3) >> 2)]; | |
109 | break; | |
110 | } | |
111 | case FDT_NOP: | |
112 | pos = &pos[1]; | |
113 | break; | |
114 | default: | |
115 | return NULL; | |
116 | } | |
117 | } | |
118 | } | |
119 | ||
68066d5b HS |
120 | /** |
121 | * efi_st_get_config_table() - get configuration table | |
122 | * | |
123 | * @guid: GUID of the configuration table | |
124 | * Return: pointer to configuration table or NULL | |
125 | */ | |
126 | static void *efi_st_get_config_table(const efi_guid_t *guid) | |
127 | { | |
128 | size_t i; | |
129 | ||
130 | for (i = 0; i < systab.nr_tables; i++) { | |
131 | if (!guidcmp(guid, &systemtab->tables[i].guid)) | |
132 | return systemtab->tables[i].table; | |
133 | } | |
134 | return NULL; | |
135 | } | |
136 | ||
06c3d5b9 HS |
137 | /* |
138 | * Setup unit test. | |
139 | * | |
140 | * @handle: handle of the loaded image | |
141 | * @systable: system table | |
142 | * @return: EFI_ST_SUCCESS for success | |
143 | */ | |
144 | static int setup(const efi_handle_t img_handle, | |
145 | const struct efi_system_table *systable) | |
146 | { | |
68066d5b | 147 | void *acpi; |
06c3d5b9 | 148 | |
68066d5b | 149 | systemtab = systable; |
06c3d5b9 HS |
150 | boottime = systable->boottime; |
151 | ||
68066d5b HS |
152 | acpi = efi_st_get_config_table(&acpi_guid); |
153 | fdt = efi_st_get_config_table(&fdt_guid); | |
154 | ||
06c3d5b9 HS |
155 | if (!fdt) { |
156 | efi_st_error("Missing device tree\n"); | |
157 | return EFI_ST_FAILURE; | |
158 | } | |
68066d5b HS |
159 | if (acpi) { |
160 | efi_st_error("Found ACPI table and device tree\n"); | |
161 | return EFI_ST_FAILURE; | |
162 | } | |
06c3d5b9 HS |
163 | return EFI_ST_SUCCESS; |
164 | } | |
165 | ||
166 | /* | |
167 | * Execute unit test. | |
168 | * | |
169 | * @return: EFI_ST_SUCCESS for success | |
170 | */ | |
171 | static int execute(void) | |
172 | { | |
173 | char *str; | |
174 | efi_status_t ret; | |
175 | ||
176 | str = get_property(L"compatible"); | |
177 | if (str) { | |
178 | efi_st_printf("compatible: %s\n", str); | |
179 | ret = boottime->free_pool(str); | |
180 | if (ret != EFI_SUCCESS) { | |
181 | efi_st_error("FreePool failed\n"); | |
182 | return EFI_ST_FAILURE; | |
183 | } | |
184 | } else { | |
185 | efi_st_printf("Missing property 'compatible'\n"); | |
186 | return EFI_ST_FAILURE; | |
187 | } | |
188 | str = get_property(L"serial-number"); | |
189 | if (str) { | |
190 | efi_st_printf("serial-number: %s\n", str); | |
191 | ret = boottime->free_pool(str); | |
192 | if (ret != EFI_SUCCESS) { | |
193 | efi_st_error("FreePool failed\n"); | |
194 | return EFI_ST_FAILURE; | |
195 | } | |
196 | } | |
197 | ||
198 | return EFI_ST_SUCCESS; | |
199 | } | |
200 | ||
201 | EFI_UNIT_TEST(fdt) = { | |
202 | .name = "device tree", | |
203 | .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, | |
204 | .setup = setup, | |
205 | .execute = execute, | |
06c3d5b9 | 206 | }; |