1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * efi_selftest_variables 4 * 5 * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de> 6 * 7 * This unit test checks the runtime services for variables: 8 * GetVariable, GetNextVariableName, SetVariable, QueryVariableInfo. 9 */ 10 11 #include <efi_selftest.h> 12 13 #define EFI_ST_MAX_DATA_SIZE 16 14 #define EFI_ST_MAX_VARNAME_SIZE 40 15 16 static struct efi_boot_services *boottime; 17 static struct efi_runtime_services *runtime; 18 static const efi_guid_t guid_vendor0 = 19 EFI_GUID(0x67029eb5, 0x0af2, 0xf6b1, 20 0xda, 0x53, 0xfc, 0xb5, 0x66, 0xdd, 0x1c, 0xe6); 21 static const efi_guid_t guid_vendor1 = 22 EFI_GUID(0xff629290, 0x1fc1, 0xd73f, 23 0x8f, 0xb1, 0x32, 0xf9, 0x0c, 0xa0, 0x42, 0xea); 24 25 /* 26 * Setup unit test. 27 * 28 * @handle handle of the loaded image 29 * @systable system table 30 */ 31 static int setup(const efi_handle_t img_handle, 32 const struct efi_system_table *systable) 33 { 34 boottime = systable->boottime; 35 runtime = systable->runtime; 36 37 return EFI_ST_SUCCESS; 38 } 39 40 /* 41 * Execute unit test. 42 */ 43 static int execute(void) 44 { 45 efi_status_t ret; 46 efi_uintn_t len; 47 u32 attr; 48 u8 v[16] = {0x5d, 0xd1, 0x5e, 0x51, 0x5a, 0x05, 0xc7, 0x0c, 49 0x35, 0x4a, 0xae, 0x87, 0xa5, 0xdf, 0x0f, 0x65,}; 50 u8 data[EFI_ST_MAX_DATA_SIZE]; 51 u16 varname[EFI_ST_MAX_VARNAME_SIZE]; 52 int flag; 53 efi_guid_t guid; 54 u64 max_storage, rem_storage, max_size; 55 56 ret = runtime->query_variable_info(EFI_VARIABLE_BOOTSERVICE_ACCESS, 57 &max_storage, &rem_storage, 58 &max_size); 59 if (ret != EFI_SUCCESS) { 60 efi_st_todo("QueryVariableInfo failed\n"); 61 } else if (!max_storage || !rem_storage || !max_size) { 62 efi_st_error("QueryVariableInfo: wrong info\n"); 63 return EFI_ST_FAILURE; 64 } 65 /* Set variable 0 */ 66 ret = runtime->set_variable(L"efi_st_var0", &guid_vendor0, 67 EFI_VARIABLE_BOOTSERVICE_ACCESS, 68 3, v + 4); 69 if (ret != EFI_SUCCESS) { 70 efi_st_error("SetVariable failed\n"); 71 return EFI_ST_FAILURE; 72 } 73 data[3] = 0xff; 74 len = 3; 75 ret = runtime->get_variable(L"efi_st_var0", &guid_vendor0, 76 &attr, &len, data); 77 if (ret != EFI_SUCCESS) { 78 efi_st_error("GetVariable failed\n"); 79 return EFI_ST_FAILURE; 80 } 81 if (efi_st_memcmp(data, v + 4, 3)) { 82 efi_st_error("GetVariable returned wrong value\n"); 83 return EFI_ST_FAILURE; 84 } 85 if (data[3] != 0xff) { 86 efi_st_error("GetVariable wrote past the end of the buffer\n"); 87 return EFI_ST_FAILURE; 88 } 89 /* Set variable 1 */ 90 ret = runtime->set_variable(L"efi_st_var1", &guid_vendor1, 91 EFI_VARIABLE_BOOTSERVICE_ACCESS, 92 8, v); 93 if (ret != EFI_SUCCESS) { 94 efi_st_error("SetVariable failed\n"); 95 return EFI_ST_FAILURE; 96 } 97 len = EFI_ST_MAX_DATA_SIZE; 98 ret = runtime->get_variable(L"efi_st_var1", &guid_vendor1, 99 &attr, &len, data); 100 if (ret != EFI_SUCCESS) { 101 efi_st_error("GetVariable failed\n"); 102 return EFI_ST_FAILURE; 103 } 104 if (len != 8) { 105 efi_st_error("GetVariable returned wrong length %u\n", 106 (unsigned int)len); 107 return EFI_ST_FAILURE; 108 } 109 if (efi_st_memcmp(data, v, 8)) { 110 efi_st_error("GetVariable returned wrong value\n"); 111 return EFI_ST_FAILURE; 112 } 113 /* Append variable 1 */ 114 ret = runtime->set_variable(L"efi_st_var1", &guid_vendor1, 115 EFI_VARIABLE_BOOTSERVICE_ACCESS | 116 EFI_VARIABLE_APPEND_WRITE, 117 7, v + 8); 118 if (ret != EFI_SUCCESS) { 119 efi_st_error("SetVariable failed\n"); 120 return EFI_ST_FAILURE; 121 } 122 len = EFI_ST_MAX_DATA_SIZE; 123 ret = runtime->get_variable(L"efi_st_var1", &guid_vendor1, 124 &attr, &len, data); 125 if (ret != EFI_SUCCESS) { 126 efi_st_error("GetVariable failed\n"); 127 return EFI_ST_FAILURE; 128 } 129 if (len != 15) 130 efi_st_todo("GetVariable returned wrong length %u\n", 131 (unsigned int)len); 132 if (efi_st_memcmp(data, v, len)) 133 efi_st_todo("GetVariable returned wrong value\n"); 134 /* Enumerate variables */ 135 boottime->set_mem(&guid, 16, 0); 136 *varname = 0; 137 flag = 0; 138 for (;;) { 139 len = EFI_ST_MAX_VARNAME_SIZE; 140 ret = runtime->get_next_variable_name(&len, varname, &guid); 141 if (ret == EFI_NOT_FOUND) 142 break; 143 if (ret != EFI_SUCCESS) { 144 efi_st_error("GetNextVariableName failed (%u)\n", 145 (unsigned int)ret); 146 return EFI_ST_FAILURE; 147 } 148 if (!efi_st_memcmp(&guid, &guid_vendor0, sizeof(efi_guid_t)) && 149 !efi_st_strcmp_16_8(varname, "efi_st_var0")) 150 flag |= 1; 151 if (!efi_st_memcmp(&guid, &guid_vendor1, sizeof(efi_guid_t)) && 152 !efi_st_strcmp_16_8(varname, "efi_st_var1")) 153 flag |= 2; 154 } 155 if (flag != 3) { 156 efi_st_error( 157 "GetNextVariableName did not return all variables\n"); 158 return EFI_ST_FAILURE; 159 } 160 /* Delete variable 1 */ 161 ret = runtime->set_variable(L"efi_st_var1", &guid_vendor1, 162 0, 0, NULL); 163 if (ret != EFI_SUCCESS) { 164 efi_st_error("SetVariable failed\n"); 165 return EFI_ST_FAILURE; 166 } 167 len = EFI_ST_MAX_DATA_SIZE; 168 ret = runtime->get_variable(L"efi_st_var1", &guid_vendor1, 169 &attr, &len, data); 170 if (ret != EFI_NOT_FOUND) { 171 efi_st_error("Variable was not deleted\n"); 172 return EFI_ST_FAILURE; 173 } 174 /* Delete variable 0 */ 175 ret = runtime->set_variable(L"efi_st_var0", &guid_vendor0, 176 0, 0, NULL); 177 if (ret != EFI_SUCCESS) { 178 efi_st_error("SetVariable failed\n"); 179 return EFI_ST_FAILURE; 180 } 181 len = EFI_ST_MAX_DATA_SIZE; 182 ret = runtime->get_variable(L"efi_st_var0", &guid_vendor0, 183 &attr, &len, data); 184 if (ret != EFI_NOT_FOUND) { 185 efi_st_error("Variable was not deleted\n"); 186 return EFI_ST_FAILURE; 187 } 188 189 return EFI_ST_SUCCESS; 190 } 191 192 EFI_UNIT_TEST(variables) = { 193 .name = "variables", 194 .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, 195 .setup = setup, 196 .execute = execute, 197 }; 198