]> git.ipfire.org Git - thirdparty/u-boot.git/blob - lib/efi_selftest/efi_selftest_set_virtual_address_map.c
net: hifemac_mdio: use log_msg_ret() correctly, report error by dev_err()
[thirdparty/u-boot.git] / lib / efi_selftest / efi_selftest_set_virtual_address_map.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * efi_selftest_set_virtual_address_map.c
4 *
5 * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
6 *
7 * This test checks the notification of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
8 * and the following services: SetVirtualAddressMap, ConvertPointer.
9 */
10
11 #include <efi_selftest.h>
12
13 static const struct efi_boot_services *boottime;
14 static const struct efi_runtime_services *runtime;
15 static struct efi_event *event;
16 static struct efi_mem_desc *memory_map;
17 static efi_uintn_t map_size;
18 static efi_uintn_t desc_size;
19 static u32 desc_version;
20 static u64 page1;
21 static u64 page2;
22 static u32 notify_call_count;
23 static bool convert_pointer_failed;
24
25 /**
26 * notify() - notification function
27 *
28 * This function is called when the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event
29 * occurs. The correct output of ConvertPointer() is checked.
30 *
31 * @event notified event
32 * @context pointer to the notification count
33 */
34 static void EFIAPI notify(struct efi_event *event, void *context)
35 {
36 void *addr;
37 efi_status_t ret;
38
39 ++notify_call_count;
40
41 addr = (void *)(uintptr_t)page1;
42 ret = runtime->convert_pointer(0, &addr);
43 if (ret != EFI_SUCCESS) {
44 efi_st_error("ConvertPointer failed\n");
45 convert_pointer_failed = true;
46 return;
47 }
48 if ((uintptr_t)addr != page1 + EFI_PAGE_SIZE) {
49 efi_st_error("ConvertPointer wrong address\n");
50 convert_pointer_failed = true;
51 return;
52 }
53
54 addr = (void *)(uintptr_t)page2;
55 ret = runtime->convert_pointer(0, &addr);
56 if (ret != EFI_SUCCESS) {
57 efi_st_error("ConvertPointer failed\n");
58 convert_pointer_failed = true;
59 return;
60 }
61 if ((uintptr_t)addr != page2 + 2 * EFI_PAGE_SIZE) {
62 efi_st_error("ConvertPointer wrong address\n");
63 convert_pointer_failed = true;
64 }
65 }
66
67 /**
68 * setup() - setup unit test
69 *
70 * The memory map is read. Boottime only entries are deleted. Two entries for
71 * newly allocated pages are added. For these virtual addresses deviating from
72 * the physical addresses are set.
73 *
74 * @handle: handle of the loaded image
75 * @systable: system table
76 * Return: EFI_ST_SUCCESS for success
77 */
78 static int setup(const efi_handle_t handle,
79 const struct efi_system_table *systable)
80 {
81 efi_uintn_t map_key;
82 efi_status_t ret;
83 struct efi_mem_desc *end, *pos1, *pos2;
84
85 boottime = systable->boottime;
86 runtime = systable->runtime;
87
88 ret = boottime->create_event(EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
89 TPL_CALLBACK, notify, NULL,
90 &event);
91 if (ret != EFI_SUCCESS) {
92 efi_st_error("could not create event\n");
93 return EFI_ST_FAILURE;
94 }
95
96 ret = boottime->get_memory_map(&map_size, NULL, &map_key, &desc_size,
97 &desc_version);
98 if (ret != EFI_BUFFER_TOO_SMALL) {
99 efi_st_error(
100 "GetMemoryMap did not return EFI_BUFFER_TOO_SMALL\n");
101 return EFI_ST_FAILURE;
102 }
103 /* Allocate extra space for newly allocated memory */
104 map_size += 3 * sizeof(struct efi_mem_desc);
105 ret = boottime->allocate_pool(EFI_BOOT_SERVICES_DATA, map_size,
106 (void **)&memory_map);
107 if (ret != EFI_SUCCESS) {
108 efi_st_error("AllocatePool failed\n");
109 return EFI_ST_FAILURE;
110 }
111 ret = boottime->get_memory_map(&map_size, memory_map, &map_key,
112 &desc_size, &desc_version);
113 if (ret != EFI_SUCCESS) {
114 efi_st_error("GetMemoryMap failed\n");
115 return EFI_ST_FAILURE;
116 }
117 ret = boottime->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
118 EFI_BOOT_SERVICES_DATA, 2, &page1);
119 if (ret != EFI_SUCCESS) {
120 efi_st_error("AllocatePages failed\n");
121 return EFI_ST_FAILURE;
122 }
123 ret = boottime->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
124 EFI_BOOT_SERVICES_DATA, 3, &page2);
125 if (ret != EFI_SUCCESS) {
126 efi_st_error("AllocatePages failed\n");
127 return EFI_ST_FAILURE;
128 }
129 /* Remove entries not relevant for runtime from map */
130 end = (struct efi_mem_desc *)((u8 *)memory_map + map_size);
131 for (pos1 = memory_map, pos2 = memory_map;
132 pos2 < end; ++pos2) {
133 switch (pos2->type) {
134 case EFI_LOADER_CODE:
135 case EFI_LOADER_DATA:
136 case EFI_BOOT_SERVICES_CODE:
137 case EFI_BOOT_SERVICES_DATA:
138 case EFI_CONVENTIONAL_MEMORY:
139 continue;
140 }
141 memcpy(pos1, pos2, desc_size);
142 ++pos1;
143 }
144
145 /*
146 * Add entries with virtual addresses deviating from the physical
147 * addresses. By choosing virtual address ranges within the allocated
148 * physical pages address space collisions are avoided.
149 */
150 pos1->type = EFI_RUNTIME_SERVICES_DATA;
151 pos1->reserved = 0;
152 pos1->physical_start = page1;
153 pos1->virtual_start = page1 + EFI_PAGE_SIZE;
154 pos1->num_pages = 1;
155 pos1->attribute = EFI_MEMORY_RUNTIME;
156 ++pos1;
157
158 pos1->type = EFI_RUNTIME_SERVICES_DATA;
159 pos1->reserved = 0;
160 pos1->physical_start = page2;
161 pos1->virtual_start = page2 + 2 * EFI_PAGE_SIZE;
162 pos1->num_pages = 1;
163 pos1->attribute = EFI_MEMORY_RUNTIME;
164 ++pos1;
165
166 map_size = (u8 *)pos1 - (u8 *)memory_map;
167
168 return EFI_ST_SUCCESS;
169 }
170
171 /**
172 * execute() - execute unit test
173 *
174 * SetVirtualAddressMap() is called with the memory map prepared in setup().
175 *
176 * The triggering of the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event is checked via
177 * the call count of the notification function.
178 *
179 * Return: EFI_ST_SUCCESS for success
180 */
181 static int execute(void)
182 {
183 efi_status_t ret;
184
185 ret = runtime->set_virtual_address_map(map_size, desc_size,
186 desc_version, memory_map);
187 if (ret != EFI_SUCCESS) {
188 efi_st_error("SetVirtualAddressMap failed\n");
189 return EFI_ST_FAILURE;
190 }
191 if (notify_call_count != 1) {
192 efi_st_error("EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE triggered %d times\n",
193 notify_call_count);
194 return EFI_ST_FAILURE;
195 }
196 if (convert_pointer_failed)
197 return EFI_ST_FAILURE;
198
199 return EFI_ST_SUCCESS;
200 }
201
202 EFI_UNIT_TEST(virtaddrmap) = {
203 .name = "virtual address map",
204 .phase = EFI_SETTING_VIRTUAL_ADDRESS_MAP,
205 .setup = setup,
206 .execute = execute,
207 };