mirror of
https://git.proxmox.com/git/fwupd
synced 2025-05-15 07:24:46 +00:00

It seems some older versions of libefi var incorrectly build the 'length' value in the DP returned from efi_generate_file_device_path(). This means we copy past the end of the allocated buffer when parsing the efi_update_info_t structure. This bug seems fixed in efivar git master, and this fix is only going to help people with older efivar versions. It's probably a good thing to be a bit more paranoid about EFI variable data anyway. DEBUG: UpdateInfo: ? 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f ???????????????????????????????????????????????????????????????????????????????????????????????????????? 0x0000 ? 07 00 00 00 20 d9 7b 69 cf 12 a9 4d 83 85 99 69 09 bc 65 59 00 00 05 00 00 00 00 00 00 00 00 00 0x0020 ? 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 01 2a 00 01 00 00 00 00 08 00 00 0x0040 ? 00 00 00 00 00 40 06 00 00 00 00 00 5a aa 97 5a 10 d5 7e 49 99 0b ca 8d 35 4d c8 6d 02 02 04 04 0x0060 ? 86 00 5c 00 45 00 46 00 49 00 5c 00 66 00 65 00 64 00 6f 00 72 00 61 00 5c 00 66 00 77 00 5c 00 0x0080 ? 66 00 77 00 75 00 70 00 64 00 2d 00 36 00 39 00 37 00 62 00 64 00 39 00 32 00 30 00 2d 00 31 00 0x00a0 ? 32 00 63 00 66 00 2d 00 34 00 64 00 61 00 39 00 2d 00 38 00 33 00 38 00 35 00 2d 00 39 00 39 00 0x00c0 ? 36 00 39 00 30 00 39 00 62 00 63 00 36 00 35 00 35 00 39 00 2e 00 63 00 61 00 70 00 00 00 7f ff 0x00e0 ? 04 00 DEBUG: DP type:0x04 subtype:0x01 size:0x002a DEBUG: DP type:0x04 subtype:0x04 size:0x0086 DEBUG: found END_ENTIRE at 0x00aa DEBUG: DP length invalid! Truncating from 0x0086 to 0x0080 DEBUG: DP type:0x7f subtype:0xff size:0x0004
338 lines
11 KiB
C
338 lines
11 KiB
C
/*
|
|
* Copyright (C) 2018 Richard Hughes <richard@hughsie.com>
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.1+
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <fwupd.h>
|
|
|
|
#include "fu-test.h"
|
|
#include "fu-ucs2.h"
|
|
#include "fu-uefi-bgrt.h"
|
|
#include "fu-uefi-common.h"
|
|
#include "fu-uefi-device.h"
|
|
#include "fu-uefi-pcrs.h"
|
|
#include "fu-uefi-vars.h"
|
|
|
|
static void
|
|
fu_uefi_pcrs_1_2_func (void)
|
|
{
|
|
gboolean ret;
|
|
g_autoptr(FuUefiPcrs) pcrs = fu_uefi_pcrs_new ();
|
|
g_autoptr(GError) error = NULL;
|
|
g_autoptr(GPtrArray) pcr0s = NULL;
|
|
g_autoptr(GPtrArray) pcrXs = NULL;
|
|
|
|
ret = fu_uefi_pcrs_setup (pcrs, &error);
|
|
g_assert_no_error (error);
|
|
g_assert_true (ret);
|
|
pcr0s = fu_uefi_pcrs_get_checksums (pcrs, 0);
|
|
g_assert_nonnull (pcr0s);
|
|
g_assert_cmpint (pcr0s->len, ==, 1);
|
|
pcrXs = fu_uefi_pcrs_get_checksums (pcrs, 999);
|
|
g_assert_nonnull (pcrXs);
|
|
g_assert_cmpint (pcrXs->len, ==, 0);
|
|
}
|
|
|
|
static void
|
|
fu_uefi_pcrs_2_0_func (void)
|
|
{
|
|
gboolean ret;
|
|
g_autoptr(FuUefiPcrs) pcrs = fu_uefi_pcrs_new ();
|
|
g_autoptr(GError) error = NULL;
|
|
g_autoptr(GPtrArray) pcr0s = NULL;
|
|
g_autoptr(GPtrArray) pcrXs = NULL;
|
|
|
|
g_setenv ("FWUPD_UEFI_TPM2_YAML_DATA",
|
|
"sha1 :\n"
|
|
" 0 : cbd9e4112727bc75761001abcb2dddd87a66caf5\n"
|
|
"sha256 :\n"
|
|
" 0 : 122de8b579cce17b0703ca9f9716d6f99125af9569e7303f51ea7f85d317f01e\n", TRUE);
|
|
|
|
ret = fu_uefi_pcrs_setup (pcrs, &error);
|
|
g_assert_no_error (error);
|
|
g_assert_true (ret);
|
|
pcr0s = fu_uefi_pcrs_get_checksums (pcrs, 0);
|
|
g_assert_nonnull (pcr0s);
|
|
g_assert_cmpint (pcr0s->len, ==, 2);
|
|
pcrXs = fu_uefi_pcrs_get_checksums (pcrs, 999);
|
|
g_assert_nonnull (pcrXs);
|
|
g_assert_cmpint (pcrXs->len, ==, 0);
|
|
}
|
|
|
|
static void
|
|
fu_uefi_pcrs_2_0_failure_func (void)
|
|
{
|
|
gboolean ret;
|
|
g_autoptr(FuUefiPcrs) pcrs = fu_uefi_pcrs_new ();
|
|
g_autoptr(GError) error = NULL;
|
|
|
|
g_setenv ("FWUPD_UEFI_TPM2_YAML_DATA",
|
|
"Something is not working properly!\n"
|
|
"999:hello\n"
|
|
"0:dave\n"
|
|
"\n", TRUE);
|
|
|
|
ret = fu_uefi_pcrs_setup (pcrs, &error);
|
|
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
|
|
g_assert_false (ret);
|
|
}
|
|
|
|
static void
|
|
fu_uefi_ucs2_func (void)
|
|
{
|
|
g_autofree guint16 *str1 = NULL;
|
|
g_autofree gchar *str2 = NULL;
|
|
str1 = fu_uft8_to_ucs2 ("hw!", -1);
|
|
g_assert_cmpint (fu_ucs2_strlen (str1, -1), ==, 3);
|
|
str2 = fu_ucs2_to_uft8 (str1, -1);
|
|
g_assert_cmpstr ("hw!", ==, str2);
|
|
}
|
|
|
|
static void
|
|
fu_uefi_bgrt_func (void)
|
|
{
|
|
gboolean ret;
|
|
g_autoptr(GError) error = NULL;
|
|
g_autoptr(FuUefiBgrt) bgrt = fu_uefi_bgrt_new ();
|
|
ret = fu_uefi_bgrt_setup (bgrt, &error);
|
|
g_assert_no_error (error);
|
|
g_assert_true (ret);
|
|
g_assert_true (fu_uefi_bgrt_get_supported (bgrt));
|
|
g_assert_cmpint (fu_uefi_bgrt_get_xoffset (bgrt), ==, 123);
|
|
g_assert_cmpint (fu_uefi_bgrt_get_yoffset (bgrt), ==, 456);
|
|
g_assert_cmpint (fu_uefi_bgrt_get_width (bgrt), ==, 54);
|
|
g_assert_cmpint (fu_uefi_bgrt_get_height (bgrt), ==, 24);
|
|
}
|
|
|
|
static void
|
|
fu_uefi_framebuffer_func (void)
|
|
{
|
|
gboolean ret;
|
|
guint32 height = 0;
|
|
guint32 width = 0;
|
|
g_autoptr(GError) error = NULL;
|
|
ret = fu_uefi_get_framebuffer_size (&width, &height, &error);
|
|
g_assert_no_error (error);
|
|
g_assert_true (ret);
|
|
g_assert_cmpint (width, ==, 456);
|
|
g_assert_cmpint (height, ==, 789);
|
|
}
|
|
|
|
static void
|
|
fu_uefi_bitmap_func (void)
|
|
{
|
|
gboolean ret;
|
|
gsize sz = 0;
|
|
guint32 height = 0;
|
|
guint32 width = 0;
|
|
g_autofree gchar *fn = NULL;
|
|
g_autofree gchar *buf = NULL;
|
|
g_autoptr(GError) error = NULL;
|
|
|
|
fn = fu_test_get_filename (TESTDATADIR, "test.bmp");
|
|
g_assert (fn != NULL);
|
|
ret = g_file_get_contents (fn, &buf, &sz, &error);
|
|
g_assert_no_error (error);
|
|
g_assert_true (ret);
|
|
g_assert_nonnull (buf);
|
|
ret = fu_uefi_get_bitmap_size ((guint8 *)buf, sz, &width, &height, &error);
|
|
g_assert_no_error (error);
|
|
g_assert_true (ret);
|
|
g_assert_cmpint (width, ==, 54);
|
|
g_assert_cmpint (height, ==, 24);
|
|
}
|
|
|
|
static void
|
|
fu_uefi_device_func (void)
|
|
{
|
|
g_autofree gchar *fn = NULL;
|
|
g_autoptr(FuUefiDevice) dev = NULL;
|
|
g_autoptr(GError) error = NULL;
|
|
|
|
fn = fu_test_get_filename (TESTDATADIR, "efi/esrt/entries/entry0");
|
|
g_assert (fn != NULL);
|
|
dev = fu_uefi_device_new_from_entry (fn, &error);
|
|
g_assert_nonnull (dev);
|
|
g_assert_no_error (error);
|
|
|
|
g_assert_cmpint (fu_uefi_device_get_kind (dev), ==, FU_UEFI_DEVICE_KIND_SYSTEM_FIRMWARE);
|
|
g_assert_cmpstr (fu_uefi_device_get_guid (dev), ==, "ddc0ee61-e7f0-4e7d-acc5-c070a398838e");
|
|
g_assert_cmpint (fu_uefi_device_get_hardware_instance (dev), ==, 0x0);
|
|
g_assert_cmpint (fu_uefi_device_get_version (dev), ==, 65586);
|
|
g_assert_cmpint (fu_uefi_device_get_version_lowest (dev), ==, 65582);
|
|
g_assert_cmpint (fu_uefi_device_get_version_error (dev), ==, 18472960);
|
|
g_assert_cmpint (fu_uefi_device_get_capsule_flags (dev), ==, 0xfe);
|
|
g_assert_cmpint (fu_uefi_device_get_status (dev), ==, FU_UEFI_DEVICE_STATUS_ERROR_UNSUCCESSFUL);
|
|
|
|
/* check enums all converted */
|
|
for (guint i = 0; i < FU_UEFI_DEVICE_STATUS_LAST; i++)
|
|
g_assert_nonnull (fu_uefi_device_status_to_string (i));
|
|
}
|
|
|
|
static void
|
|
fu_uefi_vars_func (void)
|
|
{
|
|
gboolean ret;
|
|
gsize sz = 0;
|
|
guint32 attr = 0;
|
|
g_autofree guint8 *data = NULL;
|
|
g_autoptr(GError) error = NULL;
|
|
|
|
/* check supported */
|
|
ret = fu_uefi_vars_supported (&error);
|
|
g_assert_no_error (error);
|
|
g_assert_true (ret);
|
|
|
|
/* check existing keys */
|
|
g_assert_false (fu_uefi_vars_exists (FU_UEFI_VARS_GUID_EFI_GLOBAL, "NotGoingToExist"));
|
|
g_assert_true (fu_uefi_vars_exists (FU_UEFI_VARS_GUID_EFI_GLOBAL, "SecureBoot"));
|
|
|
|
/* write and read a key */
|
|
ret = fu_uefi_vars_set_data (FU_UEFI_VARS_GUID_EFI_GLOBAL, "Test",
|
|
(guint8 *) "1", 1,
|
|
FU_UEFI_VARS_ATTR_NON_VOLATILE |
|
|
FU_UEFI_VARS_ATTR_RUNTIME_ACCESS,
|
|
&error);
|
|
g_assert_no_error (error);
|
|
g_assert_true (ret);
|
|
ret = fu_uefi_vars_get_data (FU_UEFI_VARS_GUID_EFI_GLOBAL, "Test",
|
|
&data, &sz, &attr, &error);
|
|
g_assert_no_error (error);
|
|
g_assert_true (ret);
|
|
g_assert_cmpint (sz, ==, 1);
|
|
g_assert_cmpint (attr, ==, FU_UEFI_VARS_ATTR_NON_VOLATILE |
|
|
FU_UEFI_VARS_ATTR_RUNTIME_ACCESS);
|
|
g_assert_cmpint (data[0], ==, '1');
|
|
|
|
/* delete single key */
|
|
ret = fu_uefi_vars_delete (FU_UEFI_VARS_GUID_EFI_GLOBAL, "Test", &error);
|
|
g_assert_no_error (error);
|
|
g_assert_true (ret);
|
|
g_assert_false (fu_uefi_vars_exists (FU_UEFI_VARS_GUID_EFI_GLOBAL, "Test"));
|
|
|
|
/* delete multiple keys */
|
|
ret = fu_uefi_vars_set_data (FU_UEFI_VARS_GUID_EFI_GLOBAL, "Test1", (guint8 *)"1", 1, 0, &error);
|
|
g_assert_no_error (error);
|
|
g_assert_true (ret);
|
|
ret = fu_uefi_vars_set_data (FU_UEFI_VARS_GUID_EFI_GLOBAL, "Test2", (guint8 *)"1", 1, 0, &error);
|
|
g_assert_no_error (error);
|
|
g_assert_true (ret);
|
|
ret = fu_uefi_vars_delete_with_glob (FU_UEFI_VARS_GUID_EFI_GLOBAL, "Test*", &error);
|
|
g_assert_no_error (error);
|
|
g_assert_true (ret);
|
|
g_assert_false (fu_uefi_vars_exists (FU_UEFI_VARS_GUID_EFI_GLOBAL, "Test1"));
|
|
g_assert_false (fu_uefi_vars_exists (FU_UEFI_VARS_GUID_EFI_GLOBAL, "Test2"));
|
|
|
|
/* read a key that doesn't exist */
|
|
ret = fu_uefi_vars_get_data (FU_UEFI_VARS_GUID_EFI_GLOBAL, "NotGoingToExist", NULL, NULL, NULL, &error);
|
|
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND);
|
|
g_assert_false (ret);
|
|
}
|
|
|
|
static void
|
|
fu_uefi_plugin_func (void)
|
|
{
|
|
FuUefiDevice *dev;
|
|
g_autofree gchar *esrt_path = NULL;
|
|
g_autofree gchar *sysfsfwdir = NULL;
|
|
g_autoptr(GError) error = NULL;
|
|
g_autoptr(GPtrArray) devices = NULL;
|
|
g_autoptr(GPtrArray) entries = NULL;
|
|
|
|
/* add each device */
|
|
sysfsfwdir = fu_common_get_path (FU_PATH_KIND_SYSFSDIR_FW);
|
|
esrt_path = g_build_filename (sysfsfwdir, "efi", "esrt", NULL);
|
|
entries = fu_uefi_get_esrt_entry_paths (esrt_path, &error);
|
|
g_assert_no_error (error);
|
|
g_assert_nonnull (entries);
|
|
devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
|
|
for (guint i = 0; i < entries->len; i++) {
|
|
const gchar *path = g_ptr_array_index (entries, i);
|
|
g_autoptr(GError) error_local = NULL;
|
|
g_autoptr(FuUefiDevice) dev_tmp = fu_uefi_device_new_from_entry (path, &error_local);
|
|
if (dev_tmp == NULL) {
|
|
g_debug ("failed to add %s: %s", path, error_local->message);
|
|
continue;
|
|
}
|
|
g_ptr_array_add (devices, g_object_ref (dev_tmp));
|
|
}
|
|
g_assert_cmpint (devices->len, ==, 2);
|
|
|
|
/* system firmware */
|
|
dev = g_ptr_array_index (devices, 0);
|
|
g_assert_cmpint (fu_uefi_device_get_kind (dev), ==, FU_UEFI_DEVICE_KIND_SYSTEM_FIRMWARE);
|
|
g_assert_cmpstr (fu_uefi_device_get_guid (dev), ==, "ddc0ee61-e7f0-4e7d-acc5-c070a398838e");
|
|
g_assert_cmpint (fu_uefi_device_get_version (dev), ==, 65586);
|
|
g_assert_cmpint (fu_uefi_device_get_version_lowest (dev), ==, 65582);
|
|
g_assert_cmpint (fu_uefi_device_get_version_error (dev), ==, 18472960);
|
|
g_assert_cmpint (fu_uefi_device_get_capsule_flags (dev), ==, 0xfe);
|
|
g_assert_cmpint (fu_uefi_device_get_status (dev), ==, FU_UEFI_DEVICE_STATUS_ERROR_UNSUCCESSFUL);
|
|
|
|
/* system firmware */
|
|
dev = g_ptr_array_index (devices, 1);
|
|
g_assert_cmpint (fu_uefi_device_get_kind (dev), ==, FU_UEFI_DEVICE_KIND_DEVICE_FIRMWARE);
|
|
g_assert_cmpstr (fu_uefi_device_get_guid (dev), ==, "671d19d0-d43c-4852-98d9-1ce16f9967e4");
|
|
g_assert_cmpint (fu_uefi_device_get_version (dev), ==, 3090287969);
|
|
g_assert_cmpint (fu_uefi_device_get_version_lowest (dev), ==, 1);
|
|
g_assert_cmpint (fu_uefi_device_get_version_error (dev), ==, 0);
|
|
g_assert_cmpint (fu_uefi_device_get_capsule_flags (dev), ==, 32784);
|
|
g_assert_cmpint (fu_uefi_device_get_status (dev), ==, FU_UEFI_DEVICE_STATUS_SUCCESS);
|
|
}
|
|
|
|
static void
|
|
fu_uefi_update_info_func (void)
|
|
{
|
|
g_autofree gchar *fn = NULL;
|
|
g_autoptr(FuUefiDevice) dev = NULL;
|
|
g_autoptr(FuUefiUpdateInfo) info = NULL;
|
|
g_autoptr(GError) error = NULL;
|
|
|
|
fn = fu_test_get_filename (TESTDATADIR, "efi/esrt/entries/entry0");
|
|
g_assert (fn != NULL);
|
|
dev = fu_uefi_device_new_from_entry (fn, &error);
|
|
g_assert_no_error (error);
|
|
g_assert_nonnull (dev);
|
|
g_assert_cmpint (fu_uefi_device_get_kind (dev), ==, FU_UEFI_DEVICE_KIND_SYSTEM_FIRMWARE);
|
|
g_assert_cmpstr (fu_uefi_device_get_guid (dev), ==, "ddc0ee61-e7f0-4e7d-acc5-c070a398838e");
|
|
info = fu_uefi_device_load_update_info (dev, &error);
|
|
g_assert_no_error (error);
|
|
g_assert_nonnull (info);
|
|
g_assert_cmpint (fu_uefi_update_info_get_version (info), ==, 0x7);
|
|
g_assert_cmpstr (fu_uefi_update_info_get_guid (info), ==, "697bd920-12cf-4da9-8385-996909bc6559");
|
|
g_assert_cmpint (fu_uefi_update_info_get_capsule_flags (info), ==, 0x50000);
|
|
g_assert_cmpint (fu_uefi_update_info_get_hw_inst (info), ==, 0x0);
|
|
g_assert_cmpint (fu_uefi_update_info_get_status (info), ==, FU_UEFI_UPDATE_INFO_STATUS_ATTEMPT_UPDATE);
|
|
g_assert_cmpstr (fu_uefi_update_info_get_capsule_fn (info), ==,
|
|
"/EFI/fedora/fw/fwupd-697bd920-12cf-4da9-8385-996909bc6559.cap");
|
|
}
|
|
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
g_test_init (&argc, &argv, NULL);
|
|
g_setenv ("FWUPD_SYSFSFWDIR", TESTDATADIR, TRUE);
|
|
g_setenv ("FWUPD_SYSFSDRIVERDIR", TESTDATADIR, TRUE);
|
|
g_setenv ("FWUPD_SYSFSTPMDIR", TESTDATADIR, TRUE);
|
|
|
|
/* only critical and error are fatal */
|
|
g_log_set_fatal_mask (NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL);
|
|
g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
|
|
|
|
/* tests go here */
|
|
g_test_add_func ("/uefi/pcrs1.2", fu_uefi_pcrs_1_2_func);
|
|
g_test_add_func ("/uefi/pcrs2.0", fu_uefi_pcrs_2_0_func);
|
|
g_test_add_func ("/uefi/pcrs2.0{failure}", fu_uefi_pcrs_2_0_failure_func);
|
|
g_test_add_func ("/uefi/ucs2", fu_uefi_ucs2_func);
|
|
g_test_add_func ("/uefi/variable", fu_uefi_vars_func);
|
|
g_test_add_func ("/uefi/bgrt", fu_uefi_bgrt_func);
|
|
g_test_add_func ("/uefi/framebuffer", fu_uefi_framebuffer_func);
|
|
g_test_add_func ("/uefi/bitmap", fu_uefi_bitmap_func);
|
|
g_test_add_func ("/uefi/device", fu_uefi_device_func);
|
|
g_test_add_func ("/uefi/update-info", fu_uefi_update_info_func);
|
|
g_test_add_func ("/uefi/plugin", fu_uefi_plugin_func);
|
|
return g_test_run ();
|
|
}
|