diff --git a/src/boot/chid.c b/src/boot/chid.c index 50d840aea0424..18760fd598a97 100644 --- a/src/boot/chid.c +++ b/src/boot/chid.c @@ -49,7 +49,7 @@ static char16_t *smbios_to_hashable_string(const char *str) { /* This has to be in a struct due to _cleanup_ in populate_board_chids */ typedef struct SmbiosInfo { - const char16_t *smbios_fields[_CHID_SMBIOS_FIELDS_MAX]; + char16_t *smbios_fields[_CHID_SMBIOS_FIELDS_MAX]; } SmbiosInfo; static void smbios_info_populate(SmbiosInfo *ret_info) { @@ -71,7 +71,7 @@ static void smbios_info_populate(SmbiosInfo *ret_info) { static void smbios_info_done(SmbiosInfo *info) { FOREACH_ELEMENT(i, info->smbios_fields) - free(i); + free(*i); } static EFI_STATUS populate_board_chids(EFI_GUID ret_chids[static CHID_TYPES_MAX]) { @@ -81,7 +81,7 @@ static EFI_STATUS populate_board_chids(EFI_GUID ret_chids[static CHID_TYPES_MAX] return EFI_INVALID_PARAMETER; smbios_info_populate(&info); - chid_calculate(info.smbios_fields, ret_chids); + chid_calculate((const char16_t *const *) info.smbios_fields, ret_chids); return EFI_SUCCESS; } diff --git a/src/boot/devicetree.c b/src/boot/devicetree.c index 842b96a97d9ff..2ec5ca28dd8b2 100644 --- a/src/boot/devicetree.c +++ b/src/boot/devicetree.c @@ -131,6 +131,7 @@ static const char* devicetree_get_compatible(const void *dtb) { if (struct_off % sizeof(uint32_t) != 0) return NULL; + if (struct_size % sizeof(uint32_t) != 0 || !ADD_SAFE(&end, struct_off, struct_size) || end > strings_off) @@ -150,7 +151,7 @@ static const char* devicetree_get_compatible(const void *dtb) { break; case FDT_PROP: /* At least 3 words should present: len, name_off, c (nul-terminated string always has non-zero length) */ - if (i + 3 >= size_words || cursor[++i] != 0) + if (i + 3 >= size_words) return NULL; len = be32toh(cursor[++i]); name_off = be32toh(cursor[++i]); diff --git a/src/boot/pe.c b/src/boot/pe.c index 00739a7c7422c..9af6ca0dd4470 100644 --- a/src/boot/pe.c +++ b/src/boot/pe.c @@ -253,7 +253,7 @@ static void pe_locate_sections_internal( j->VirtualSize, device_table, device, - i)) + (PTR_TO_SIZE(j) - PTR_TO_SIZE(section_table)) / sizeof(*j))) continue; } diff --git a/src/fundamental/chid-fundamental.c b/src/fundamental/chid-fundamental.c index 55b04fa2ab70d..01045176f5227 100644 --- a/src/fundamental/chid-fundamental.c +++ b/src/fundamental/chid-fundamental.c @@ -15,14 +15,12 @@ */ #if SD_BOOT -# include "efi-string.h" # include "util.h" #else # include # include -# include # include -#define strsize16(str) ((char16_strlen(str) + 1) * sizeof(char16_t)) +#define strlen16 char16_strlen #endif #include "chid-fundamental.h" @@ -44,7 +42,7 @@ static void get_chid(const char16_t *const smbios_fields[static _CHID_SMBIOS_FIE if ((mask >> i) & 1) { if (i > 0) sha1_process_bytes(L"&", 2, &ctx); - sha1_process_bytes(smbios_fields[i], strsize16(smbios_fields[i]), &ctx); + sha1_process_bytes(smbios_fields[i], strlen16(smbios_fields[i]) * sizeof(char16_t), &ctx); } uint8_t hash[SHA1_DIGEST_SIZE]; @@ -112,7 +110,8 @@ static const uint32_t chid_smbios_table[CHID_TYPES_MAX] = { void chid_calculate(const char16_t *const smbios_fields[static _CHID_SMBIOS_FIELDS_MAX], EFI_GUID ret_chids[static CHID_TYPES_MAX]) { assert(smbios_fields); assert(ret_chids); - for (size_t i = 0; i < _CHID_SMBIOS_FIELDS_MAX; i++) + + for (size_t i = 0; i < CHID_TYPES_MAX; i++) if (chid_smbios_table[i] != 0) get_chid(smbios_fields, chid_smbios_table[i], &ret_chids[i]); else diff --git a/src/fundamental/chid-fundamental.h b/src/fundamental/chid-fundamental.h index e8c5c1add285a..1e582932fd293 100644 --- a/src/fundamental/chid-fundamental.h +++ b/src/fundamental/chid-fundamental.h @@ -2,6 +2,12 @@ #pragma once +#if SD_BOOT +# include "efi-string.h" +#else +# include +#endif + #include "efi-fundamental.h" #include "string-util-fundamental.h" diff --git a/src/fundamental/efi-fundamental.h b/src/fundamental/efi-fundamental.h index 75cfd23b8c7d7..f6729293a9c28 100644 --- a/src/fundamental/efi-fundamental.h +++ b/src/fundamental/efi-fundamental.h @@ -2,7 +2,10 @@ #pragma once #if !SD_BOOT +# include # include +# include + /* Matches EFI API definition of the same structure for userspace */ typedef struct { uint32_t Data1; @@ -11,6 +14,10 @@ typedef struct { uint8_t Data4[8]; } EFI_GUID; +static inline bool efi_guid_equal(const EFI_GUID *a, const EFI_GUID *b) { + return memcmp(a, b, sizeof(EFI_GUID)) == 0; +} + typedef struct { EFI_GUID SignatureOwner; uint8_t SignatureData[]; diff --git a/src/shared/tests.h b/src/shared/tests.h index a7c2600d38354..8caf4d9d83d7c 100644 --- a/src/shared/tests.h +++ b/src/shared/tests.h @@ -559,3 +559,22 @@ static inline int run_test_table(void) { abort(); \ } \ }) + +#define EFI_GUID_Fmt "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" +#define EFI_GUID_Arg(guid) (guid).Data1, (guid).Data2, (guid).Data3, \ + (guid).Data4[0], (guid).Data4[1], (guid).Data4[2], (guid).Data4[3], \ + (guid).Data4[4], (guid).Data4[5], (guid).Data4[6], (guid).Data4[7] \ + +#define ASSERT_EQ_EFI_GUID(expr1, expr2) \ + ({ \ + typeof(expr1) _expr1 = (expr1); \ + typeof(expr2) _expr2 = (expr2); \ + if (!efi_guid_equal(_expr1, _expr2)) { \ + log_error("%s:%i: Assertion failed: expected \"%s == %s\", but " EFI_GUID_Fmt \ + " != " EFI_GUID_Fmt, \ + PROJECT_FILE, __LINE__, \ + #expr1, #expr2, \ + EFI_GUID_Arg(*_expr1), EFI_GUID_Arg(*_expr2)); \ + abort(); \ + } \ + }) diff --git a/src/test/meson.build b/src/test/meson.build index 9f74a7b56aa84..7d73e860c1f8b 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -58,6 +58,7 @@ simple_tests += files( 'test-cgroup-util.c', 'test-cgroup.c', 'test-chase.c', + 'test-chid.c', 'test-clock.c', 'test-color-util.c', 'test-compare-operator.c', diff --git a/src/test/test-chid.c b/src/test/test-chid.c new file mode 100644 index 0000000000000..ae1726679d050 --- /dev/null +++ b/src/test/test-chid.c @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "chid-fundamental.h" +#include "string-util.h" +#include "tests.h" + +const char16_t *const test_fields[_CHID_SMBIOS_FIELDS_MAX] = { + [CHID_SMBIOS_MANUFACTURER] = u"Micro-Star International Co., Ltd.", + [CHID_SMBIOS_PRODUCT_NAME] = u"MS-7D70", + [CHID_SMBIOS_PRODUCT_SKU] = u"To be filled by O.E.M.", + [CHID_SMBIOS_FAMILY] = u"To be filled by O.E.M.", + [CHID_SMBIOS_BASEBOARD_PRODUCT] = u"MPG X670E CARBON WIFI (MS-7D70)", + [CHID_SMBIOS_BASEBOARD_MANUFACTURER] = u"Micro-Star International Co., Ltd.", +}; + +/* Actual output of `fwupdtool hwids`: +BiosVendor: American Megatrends International, LLC. +BiosVersion: 1.E5 +BiosMajorRelease: 5 +BiosMinorRelease: 32 +FirmwareMajorRelease: ff +FirmwareMinorRelease: ff +Manufacturer: Micro-Star International Co., Ltd. +Family: To be filled by O.E.M. +ProductName: MS-7D70 +ProductSku: To be filled by O.E.M. +EnclosureKind: 3 +BaseboardManufacturer: Micro-Star International Co., Ltd. +BaseboardProduct: MPG X670E CARBON WIFI (MS-7D70) +Hardware IDs +------------ +{f59668ca-22bc-52a0-b6b5-1f6ce81b08e0} <- Manufacturer + Family + ProductName + ProductSku + BiosVendor + BiosVersion + BiosMajorRelease + BiosMinorRelease +{f735f7a0-40da-5bfe-8ac2-0090532ee6d0} <- Manufacturer + Family + ProductName + BiosVendor + BiosVersion + BiosMajorRelease + BiosMinorRelease +{25880e68-e005-5ca7-88b6-650de596604f} <- Manufacturer + ProductName + BiosVendor + BiosVersion + BiosMajorRelease + BiosMinorRelease +{01e09b32-de05-56ca-b9d1-9486ad5f381d} <- Manufacturer + Family + ProductName + ProductSku + BaseboardManufacturer + BaseboardProduct +{cad87a11-1813-507b-9aab-9a5f457b649c} <- Manufacturer + Family + ProductName + ProductSku +{377c823d-60d1-55b0-9678-76cd2af9d086} <- Manufacturer + Family + ProductName +{28ac9cf2-5bde-59f7-aebe-4b3d008090fe} <- Manufacturer + ProductSku + BaseboardManufacturer + BaseboardProduct +{e821e0e2-e11a-5e94-bf5d-ffe53c5e5048} <- Manufacturer + ProductSku +{1c092f1d-dc7b-564f-8a3d-128d7292fab8} <- Manufacturer + ProductName + BaseboardManufacturer + BaseboardProduct +{c12c1f4a-332d-5d72-aa36-7a3d413b479a} <- Manufacturer + ProductName +{28ac9cf2-5bde-59f7-aebe-4b3d008090fe} <- Manufacturer + Family + BaseboardManufacturer + BaseboardProduct +{e821e0e2-e11a-5e94-bf5d-ffe53c5e5048} <- Manufacturer + Family +{bdd76d3e-147f-58a9-a0b2-42136454ed07} <- Manufacturer + EnclosureKind +{b2e58e8b-fb10-5cd0-8fb0-5bd931f1871a} <- Manufacturer + BaseboardManufacturer + BaseboardProduct +{50af5797-a2f2-58b1-9a1a-453bcbb2e025} <- Manufacturer +Extra Hardware IDs +------------------ +{e6ff1b45-1955-5701-89ab-04fe2280cb4a} <- Manufacturer + Family + ProductName + ProductSku + BiosVendor +{8c4a76b9-e29e-5a3c-9072-9664898ecae6} <- Manufacturer + Family + ProductName + BiosVendor +{7b3d90ce-ed79-5951-a48a-764ea9f11146} <- Manufacturer + BiosVendor +*/ + +static const EFI_GUID actual_chids[] = { + {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {0x01e09b32, 0xde05, 0x56ca, {0xb9, 0xd1, 0x94, 0x86, 0xad, 0x5f, 0x38, 0x1d}}, + {0xcad87a11, 0x1813, 0x507b, {0x9a, 0xab, 0x9a, 0x5f, 0x45, 0x7b, 0x64, 0x9c}}, + {0x377c823d, 0x60d1, 0x55b0, {0x96, 0x78, 0x76, 0xcd, 0x2a, 0xf9, 0xd0, 0x86}}, + {0x28ac9cf2, 0x5bde, 0x59f7, {0xae, 0xbe, 0x4b, 0x3d, 0x00, 0x80, 0x90, 0xfe}}, + {0xe821e0e2, 0xe11a, 0x5e94, {0xbf, 0x5d, 0xff, 0xe5, 0x3c, 0x5e, 0x50, 0x48}}, + {0x1c092f1d, 0xdc7b, 0x564f, {0x8a, 0x3d, 0x12, 0x8d, 0x72, 0x92, 0xfa, 0xb8}}, + {0xc12c1f4a, 0x332d, 0x5d72, {0xaa, 0x36, 0x7a, 0x3d, 0x41, 0x3b, 0x47, 0x9a}}, + {0x28ac9cf2, 0x5bde, 0x59f7, {0xae, 0xbe, 0x4b, 0x3d, 0x00, 0x80, 0x90, 0xfe}}, + {0xe821e0e2, 0xe11a, 0x5e94, {0xbf, 0x5d, 0xff, 0xe5, 0x3c, 0x5e, 0x50, 0x48}}, + {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {0xb2e58e8b, 0xfb10, 0x5cd0, {0x8f, 0xb0, 0x5b, 0xd9, 0x31, 0xf1, 0x87, 0x1a}}, + {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, +}; + +TEST(chid) { + /* Results compared with output of 'fwupdtool hwids' */ + EFI_GUID chids[CHID_TYPES_MAX]; + chid_calculate(test_fields, chids); + for (size_t i = 0; i < ELEMENTSOF(chids); i++) + ASSERT_EQ_EFI_GUID(&chids[i], &actual_chids[i]); +} + +static int intro(void) { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + return EXIT_SUCCESS; +#else + return log_tests_skipped("cannot run CHID calculation on big-endian machine"); +#endif +} + +DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO, intro);