1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <drivers/efi/efivars.h>
4 #include <vendorcode/intel/edk2/UDK2017/MdePkg/Include/Pi/PiFirmwareVolume.h>
5 #include <vendorcode/intel/edk2/UDK2017/MdeModulePkg/Include/Guid/VariableFormat.h>
7 #include <tests/test.h>
10 /* Dummy firmware volume header for a 0x30000 byte partition with a single entry
11 * in a formatted variable store.
13 static const uint8_t FVH
[] = {
14 /* EFI_FIRMWARE_VOLUME_HEADER */
15 /* UINT8 ZeroVector[16] */
16 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
18 /* EFI_GUID FileSystemGuid */
19 0x8d, 0x2b, 0xf1, 0xff, 0x96, 0x76, 0x8b, 0x4c, 0xa9, 0x85, 0x27, 0x47, 0x07, 0x5b,
22 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
23 /* UINT32 Signature */
24 0x5f, 0x46, 0x56, 0x48,
25 /* EFI_FVB_ATTRIBUTES_2 Attributes */
26 0x36, 0x0e, 0x00, 0x00,
27 /* UINT16 HeaderLength */
31 /* UINT16 ExtHeaderOffset */
33 /* UINT8 Reserved[1] */
37 /* EFI_FV_BLOCK_MAP_ENTRY BlockMap[2] */
38 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
39 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41 /* Variable Info Header */
42 /* EFI_GUID Signature */
43 0x78, 0x2c, 0xf3, 0xaa, 0x7b, 0x94, 0x9a, 0x43, 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3,
46 0xb8, 0xff, 0x00, 0x00,
53 /* UINT32 Reserved1 */
54 0x00, 0x00, 0x00, 0x00,
55 /* AUTHENTICATED_VARIABLE_HEADER */
62 /* UINT32 Attributes */
63 0x07, 0x00, 0x00, 0x00,
64 /* UINT64 MonotonicCount */
65 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
66 /* EFI_TIME TimeStamp */
67 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
68 0xff, 0xff, 0xff, 0xff,
69 /* UINT32 PubKeyIndex */
70 0xff, 0xff, 0xff, 0xff,
72 0x12, 0x00, 0x00, 0x00,
74 0x09, 0x00, 0x00, 0x00,
75 /* EFI_GUID VendorGuid */
76 0x1d, 0x4c, 0xae, 0xce, 0x5b, 0x33, 0x85, 0x46, 0xa4, 0xa0, 0xfc, 0x4a,
77 0x94, 0xee, 0xa0, 0x85,
79 0x63, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x62, 0x00,
80 0x6f, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x00, 0x00,
82 0x69, 0x73, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x00,
85 #define FVH_CHECKSUMMED_SIZE (sizeof(EFI_FIRMWARE_VOLUME_HEADER) + 8 + sizeof(EFI_GUID))
87 static struct region_device flash_rdev_rw
;
88 static uint8_t flash_buffer
[0x30000];
90 static const char *name
= "coreboot";
92 static void mock_rdev(bool init
)
95 /* Emulate NOR flash by setting all bits to 1 */
96 memset(flash_buffer
, 0xff, sizeof(flash_buffer
));
97 /* Place _FVH and VIH headers, as well as test data */
98 memcpy(flash_buffer
, FVH
, sizeof(FVH
));
101 rdev_chain_mem_rw(&flash_rdev_rw
, flash_buffer
, sizeof(flash_buffer
));
104 static const EFI_GUID EficorebootNvDataGuid
= {
105 0xceae4c1d, 0x335b, 0x4685, { 0xa4, 0xa0, 0xfc, 0x4a, 0x94, 0xee, 0xa0, 0x85 } };
107 /* Test valid and corrupted FVH header */
108 static void efi_test_header(void **state
)
117 /* Test variable lookup with intact header */
119 ret
= efi_fv_get_option(&flash_rdev_rw
, &EficorebootNvDataGuid
, name
, buf
, &size
);
120 assert_int_equal(ret
, CB_SUCCESS
);
121 assert_int_equal(size
, strlen("is great")+1);
122 assert_string_equal((const char *)buf
, "is great");
124 for (i
= 0; i
< FVH_CHECKSUMMED_SIZE
; i
++) {
128 flash_buffer
[i
] ^= 0xff;
131 ret
= efi_fv_get_option(&flash_rdev_rw
, &EficorebootNvDataGuid
, name
, buf
,
133 assert_int_not_equal(ret
, CB_SUCCESS
);
137 /* Write with the same key and value should not modify the store */
138 static void efi_test_noop_existing_write(void **state
)
145 ret
= efi_fv_set_option(&flash_rdev_rw
,
146 &EficorebootNvDataGuid
,
149 strlen("is great") + 1);
151 assert_int_equal(ret
, CB_SUCCESS
);
153 for (i
= sizeof(FVH
); i
< sizeof(flash_buffer
); i
++)
154 assert_int_equal(flash_buffer
[i
], 0xff);
157 static void efi_test_new_write(void **state
)
166 ret
= efi_fv_set_option(&flash_rdev_rw
, &EficorebootNvDataGuid
,
167 name
, "is awesome", strlen("is awesome") + 1);
168 assert_int_equal(ret
, CB_SUCCESS
);
170 /* New variable has been written */
171 assert_int_equal(flash_buffer
[ALIGN_UP(sizeof(FVH
), 4)], 0xaa);
172 assert_int_equal(flash_buffer
[ALIGN_UP(sizeof(FVH
), 4) + 1], 0x55);
174 /* Remaining space is blank */
175 for (i
= ALIGN_UP(sizeof(FVH
), 4) + 89; i
< sizeof(flash_buffer
); i
++)
176 assert_int_equal(flash_buffer
[i
], 0xff);
180 memset(buf
, 0, sizeof(buf
));
182 ret
= efi_fv_get_option(&flash_rdev_rw
, &EficorebootNvDataGuid
, name
, buf
,
184 assert_int_equal(ret
, CB_SUCCESS
);
185 assert_int_equal(size
, strlen("is awesome")+1);
187 assert_int_equal(flash_buffer
[ALIGN_UP(sizeof(FVH
), 4) + 1], 0x55);
188 assert_string_equal((const char *)buf
, "is awesome");
193 const struct CMUnitTest tests
[] = {
194 cmocka_unit_test(efi_test_header
),
195 cmocka_unit_test(efi_test_noop_existing_write
),
196 cmocka_unit_test(efi_test_new_write
)
199 return cb_run_group_tests(tests
, NULL
, NULL
);